Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 days ago.
Improve this question
I have always been haunted by this question by myself each time I write any classes: Where should I inject the class dependency. Should it be given to __init__ constructor or to the specific method that uses the dependent object..
Take the below 2 pieces of python code for example, to me they function exactly the same way (I might be wrong in saying this, let me know if you have different opinion).
My questions are:
which design is better in this case, and why?
In general, what is the rule to decide if the dependency should be given to the constructor or the specific method?
Any thoughts or references would be really much appreciated!
class TextFile:
def save_text(self, text):
print("Below texts saved to file")
print(text)
class TextWriter:
def __init__(self):
self.text = ""
def write_text(self, text):
self.text += text
def save_text(self, saver): # dependency injected in the specific method
saver.save_text(self.text)
if __name__ == "__main__":
tf_saver = TextFile()
writer = TextWriter()
writer.write_text("Here is some text")
writer.save_text(saver=tf_saver)
class TextFile:
def save_text(self, text):
print("Below texts saved to file")
print(text)
class TextWriter:
def __init__(self, saver): # dependency injected in the constructor
self.text = ""
self.saver = saver
def write_text(self, text):
self.text += text
def save_text(self):
self.saver.save_text(self.text)
if __name__ == "__main__":
tf_saver = TextFile()
writer = TextWriter(tf_saver)
writer.write_text("Here is some text")
writer.save_text()
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
The community is reviewing whether to reopen this question as of 5 days ago.
Improve this question
I wrote a class for which I later needed to write a specific logger.
In this particular case, standard Python logging doesn't work for me, for several reasons.
To simplify, it turned out something like this:
class Counter(object):
def __init__(self):
self.foo = 0
self.status = 'Off'
def counter_foo(self, n):
self.foo += n
def set_status(self, status):
self.status = status
def result(self):
print(f'Foo: {self.foo}')
print(self.status)
class First(object):
def __init__(self):
self.counter = Counter()
self.status = 'On'
def print_foo(self, n=1):
# This part is changing
print('foo' * n)
# This part doesn't change.
self.counter.counter_foo(n)
if self.status == 'On':
self.counter.set_status(self.status)
def end(self):
print('Bye!')
self.counter.result()
def main():
foobar = First()
foobar.print_foo(8)
foobar.end()
Part of the code in the First function changes in different projects. But the part about calling the Counter is always the same. In what ways can I redo it for easy transfer from project to project. Is a mixin suitable here, or is it better to make a decorator out of the Counter?
In a real project, in each function of the First class, there may be 3-5 calls to counter functions, but they are always the same.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
During coding I came across with this simple recursion problem and I wrote an example of my code below. I ask somebody to find a good way to solve the problem. I guess it is supposed to write third class containing the relations.
from __future__ import annotations
from typing import Set
class Author:
def __init__(self):
self.books: Set[Book] = set()
def add_book(self, book: Book):
self.books.add(book)
book.add_author(self)
class Book:
def __init__(self):
self.authors: Set[Author] = set()
def add_author(self, author: Author):
self.authors.add(author)
author.add_book(self)
author = Author()
book = Book()
author.add_book(book) #RecursionError: maximum recursion depth exceeded while calling a Python object
The add_book() and add_author() methods call each other, so you get into an infinite loop.
The methods should check whether they're already added and not do anything, this will stop the recursion.
class Author:
def __init__(self):
self.books: Set[Book] = set()
def add_book(self, book: Book):
if book not in self.books:
self.books.add(book)
book.add_author(self)
class Book:
def __init__(self):
self.authors: Set[Author] = set()
def add_author(self, author: Author):
if author not in self.authors:
self.authors.add(author)
author.add_book(self)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Turtle=Animal("Turtle")
Turtle.set_category("reptile")
and
class Turtle(Animal):
category="reptile"
While learning object composition in python i came across a problem in which latter worked but former did not.
this was the class
class Animal:
name = ""
category = ""
def __init__(self, name):
self.name = name
def set_category(self, category):
self.category = category
These two sequences should behave the same:
turtle=Animal("Turtle")
turtle.set_category("reptile")
and
class Turtle(Animal):
category="reptile"
name = "Turtle"
turtle = Turtle()
The two turtle objects will behave identically.
In the first piece of code you are defining an instance of the Animal class stored in the Turtle variable, whereas in the second piece of code you are defining a new class called Turtle that will inherit from the Animal class.
Read more about class objects here: https://docs.python.org/3/tutorial/classes.html#class-objects
Read more about class inheritance here: https://docs.python.org/3/tutorial/classes.html#inheritance
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I made decorators to cache the data and in particular to list the files contained in a cache file. I specify that my code works perfectly but I dont know if it is a good practice because I decorate a method of my class with my decorator "# cache.listcachedir (...)" which in reality does not call upon my method but return a result (see code above).
My decorator (in cache.py):
def listcachedir(directory):
def decorator(func):
#wraps(func)
def wrapper(self):
# Join base cache dir to directory
fdir = self.locate(directory)
if os.path.isdir(fdir):
return os.listdir(fdir)
else:
raise CacheNotFoundError()
return wrapper
return decorator
In my other py file:
class Analitics:
def __init__(self, ):
self.base_cache_dir = ".../..."
...
def locate(directory):
return os.path.join(self.base_cache_dir, directory)
...
class Analyzer(Analitics):
def __init__(self):
Analitics.__init__(self)
#cache.listcachedir('my_cache')
def getCacheList(self): return # Return any the wrapper return result
if __name__=="__main__":
ana = Analyzer()
print(ana.getCacheList()) # Works
Yes, this is bad practice because it's needlessly confusing. You can define the function more simply as:
(cache.py)
def listcachedir(analitics, directory):
# Join base cache dir to directory
fdir = analitics.locate(directory)
if os.path.isdir(fdir):
return os.listdir(fdir)
else:
raise CacheNotFoundError()
and then:
class Analyzer(Analitics):
def __init__(self):
Analitics.__init__(self)
def getCacheList(self):
return listcachedir(self, 'my_cache')
This does exactly the same thing (including separating the listcachedir implementation into its own module), but without all the confusing layers of indirection.
I find the use of a decorator misleading here.
You don't use the func argument. I expect a decorator to do something with the function (or class) it decorates. Because if it does not, what's the point of defining the function that's being decorated?
You could write your code like this:
def make_cachemethod(directory):
def cachemethod(self):
fdir = self.locate(directory)
if os.path.isdir(fdir):
return os.listdir(fdir)
else:
raise CacheNotFoundError()
return cachemethod
class Analyzer(Analitics):
getCacheList = make_cachemethod('my_cache')
# more code here
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I'd like to know what's the best way to organize a class in Python as checking on previous questions here I didn't find exactly what I needed. Let's say I have this class:
class A():
def __init__(self):
self.data = #A pandas dataframe I get from an online API
I have then many functions inside this class which I'd like to organize. All these functions will need the Dataframe contained in self.data as parameter.
I thought to create a subclass for every group of functions but I didn't find a way to then refer to self.data from inside the subclass.
I found then online that I could organize the functions in different modules. However how to I pass the Dataframe in self.data as parameter to the functions? Let's say function1 is defined as following:
def function1(self):
print (self.data)
If the function was defined inside the class, I could do this:
x = A()
x.function1()
and get the print without passing self.data as parameter. How would I do this if a function is defined in another module and I import it in the main class without passing self.data as parameter every time? Thanks in advance.
EDIT:
If I do:
class A():
def __init__(self):
self.x = 1
self.b = self.B()
class B(A):
def print(self):
print(self.x)
I get an error saying "A is not defined"
I like your approach to create subclasses for each group of methods. First start with a base class which stores your data
class DataBase:
def __init__(self, data):
self._data = data
Then write your different groups of methods ...
class GroupB(DataBase):
def func_b1(self):
return self._data
def func_b2(self):
return self._data
class GroupA(DataBase):
def func_a1(self):
return self._data
def func_a2(self):
return self._data
... and finally collect all these groups together
class MyData(GroupA, GroupB):
pass
>>> d = MyData(123)
>>> d.func_a1()
123
>>> d.func_b2()
123
I hope this helps you.