In the following example, the class MyExample
read a list of filenames which have underscores in their file names.
class MyExample(object):
def __init__(self, location: str):
self.location = location
def get_file_names(self):
# For simplicity, lets just return an example of the output
return ["my_file_name_01.txt", "my_file_name_02.txt"]
def get_file_name_number(self):
# Idem as before.
return ["file_name_01.txt", "file_name_02.txt"]
def get_file_size(self):
# It does not return a list of strings so the desired
# property or function will not be applied here
return [3800, 4000]
When the code is executed, the results are
my_object = MyExample("./a/random/path")
print(my_object.get_file_names())
print(my_object.get_file_name_number())
print(my_object.get_file_size())
# The results:
['my_file_name_01.txt', 'my_file_name_02.txt']
['file_name_01.txt', 'file_name_02.txt']
[3800, 4000]
Now, I would like to find a way to apply a function or property (let's call it to_dot
) that can replace the underscores for dots from the output of get_file_names()
and get_file_name_number
.
The final code should have to return something like
# Calling this function with .to_dots
my_object.get_file_names().to_dots
["my.file.name.01.txt", "my.file.name.02.txt"] # <-- The desired output
# Calling this function with .to_dots
my_object.get_file_name_number().to_dots
["file.name.01.txt", "file.name.02.txt"] # <-- The desired output
# Calling this function with .to_dots
my_object.get_file_name_number().to_dots
AttributeError # # <-- The desired output ... or something similar
Is there a way to add the to_dots
to the class MyExample
in order to replace the underscores of some of the methods inside?
I am not very familiar with decorators but I suspect there could be a trick to do that. So far I have unsuccessfully tried with @property
but as far as I know, there are many types of decorators.... Or maybe it can be done without decorators and I am very lost.
Thank you.
CodePudding user response:
Define your own decorator:
def to_dots(func):
def inner():
original_return = func()
return [item.replace('_','.') for item in original_return ]
return inner
And use it as :
@to_dots
def get_file_names(self):
CodePudding user response:
You could do something like this:
from collections import UserList
class MyList(UserList):
@property
def to_dots(self):
return [s.replace("_", ".") for s in self.data]
class MyExample(object):
def __init__(self, location: str):
self.location = location
def get_file_names(self):
return MyList(["my_file_name_01.txt", "my_file_name_02.txt"])
Result for
my_object = MyExample("./a/random/path")
print(my_object.get_file_names())
print(my_object.get_file_names().to_dots)
is
['my_file_name_01.txt', 'my_file_name_02.txt']
['my.file.name.01.txt', 'my.file.name.02.txt']
CodePudding user response:
Why not pass the required output format (dotted or not) as optional argument to those methods?
class MyExample(object):
def __init__(self, location: str):
self.location = location
@staticmethod
def map_list(lst, dotted=False):
return [s.replace("_", ".") for s in lst] if dotted else lst
def get_file_names(self, dotted=False):
return self.map_list(["my_file_name_01.txt", "my_file_name_02.txt"], dotted)
def get_file_name_number(self, dotted=False):
return self.map_list(["file_name_01.txt", "file_name_02.txt"], dotted)
def get_file_size(self):
return [3800, 4000]
my_object = MyExample("./a/random/path")
print(my_object.get_file_names()) # Underscores untouched
print(my_object.get_file_name_number(dotted=True)) # Underscores replaced
print(my_object.get_file_size())
CodePudding user response:
You can use a class decorator to apply a function decorator to the specified class methods.
from functools import wraps
import inspect
def dec_methods(decorator, *members):
"""Class decorator to apply specfied decorator to specified members of class."""
def dec_the_class(cls):
for name, m in inspect.getmembers(cls, inspect.isfunction):
if name in members:
setattr(cls, name, decorator(m))
return cls
return dec_the_class
def to_dots(func):
"""Function decorator to replace '_' with dots in list of strings returned."""
@wraps(func)
def wrapped(*args, **kwargs):
results = func(*args, **kwargs)
results = [result.replace('_', '.') for result in results]
return results
return wrapped
@dec_methods(to_dots, 'get_file_names', 'get_file_name_number')
class MyExample(object):
def __init__(self, location: str):
self.location = location
def get_file_names(self):
# For simplicity, lets just return an example of the output
return ["my_file_name_01.txt", "my_file_name_02.txt"]
def get_file_name_number(self):
# Idem as before.
return ["file_name_01.txt", "file_name_02.txt"]
def get_file_size(self):
# It does not return a list of strings so the desired
# property or function will not be applied here
return [3800, 4000]
my_object = MyExample("./a/random/path")
print(my_object.get_file_names()) # -> ['my.file.name.01.txt', 'my.file.name.02.txt']
print(my_object.get_file_name_number()) # -> ['file.name.01.txt', 'file.name.02.txt']
print(my_object.get_file_size()) # -> [3800, 4000]