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 3 years ago.
Improve this question
I was looking for a way how we can modify existing staticmethod decorator in python to add custom behavior. Say, calling another method in a class each time a static method is used.
I was stuck in a problem with MongoDB which required calling a method to manually set the Collection Name.
The following points give a description of the problem I'm stuck at:
I made a Database Class which acted as a wrapper for pymongo
I made 2 classes which used the Database Class I made for making transaction with MongoDB
Collection name's assigned to each class as a static variable
Example :
User Class's collection name -> Users,
Quiz Class's collection name -> Quiz
Database Class (wrapper) maintained it's own static variable for Collection name, which was assigned by whichever class required to make transactions with the help of it.
The PROBLEM: Whenever I made a transaction for Quiz class first, it assigned Collection name to Database Class, but as soon as I made a transaction with User Class, Quiz Class's Collection name was used.
I made transactions using static methods in those Classes, The SOLUTION I thought of was modifying staticmethod in a way that it automatically reassigns the Collection name to the Database Class each time the static method is called.
Create a new decorator instead that calls staticmethod. I think this will work.
def customstatic(fun):
def decorator(*args, **kwargs):
def wrapper():
return fun(*args, **kwargs)
# do custom stuff here
return staticmethod(wrapper)
return decorator
To add an alternative to #blueteeth 's answer.
This works but most linters will complain about it.
def custom_method(func):
#staticmethod
def static(*args, **kwargs):
# do stuff
func(*args, **kwargs)
return static
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 21 days ago.
Improve this question
I am trying to use one variable obtained from one function in other function. However , it gives error. Let me explain it wih my code.
class Uygulama(object):
def __init__(self):
self.araclar()
self.refresh()
self.gateway_find()
def refresh(self):
self.a, self.b = srp(Ether(dst="FF:FF:FF:FF:FF:FF") / ARP(pdst=self.ip_range2), timeout=2, iface="eth0",
retry=3)
#There are unrelated codes here
def gateway_find(self):
#Find ip any range in which you conncet:
self.ip_range=conf.route.route("0.0.0.0")[1]
self.ip_range1=self.ip_range.rpartition(".")[0]
self.ip_range2=self.iprange_1+".0/24"
When , run the foregoing codes , i get this error AttributeError: 'Uygulama' object has no attribute 'ip_range2'
How can i use such variable which are obtained from other function in the other function. How can i fix my problem ?
Call order of init functions
Place function that define attribute first
In the __init__ function, you call refresh, who use (need) ip_range2 before gateway_find who create the attribute and set a value to it. Swap the two lines, you should be fine.
def __init__(self):
self.araclar()
self.gateway_find() # gateway_find will set the ip_range attribute
self.refresh() # So refresh function will be able to access it
Usually, we place init functions first, then function that will call post-init processes like refresh.
Class attribute default value
Alternatively, you can define a default value for ip_range2 like this:
class Uygulama(object):
ip_range2 = None
def __init__(self):
self.araclar()
self.refresh()
self.gateway_find()
def refresh(self):
self.a, self.b = srp(Ether(dst="FF:FF:FF:FF:FF:FF") / ARP(pdst=self.ip_range2), timeout=2, iface="eth0", retry=3)
Be aware that such default value is shared with all other instances of the class if not redefined in __init__, so if it's a mutable (like a list), it might create really weird bugs.
Usually, prefer defining value in the __init__ like you do with the gateway fct.
That error explains correctly that you do not have a class attribute called ip_range2. You need to define the class attribute first.
class Uygulama(object):
ip_range2 = ''
...
then use that with self.ip_range2.
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 3 years ago.
Improve this question
I am practicing python classes. I got that classes variables are shared among all the instances, while instance variables belongs to each object, and thus need to be defined for each instance. In the following classes, in reference to the variable raise_amount, if I write the last code line like that: self.pay = int(self.pay * Employee.raise_amount), the behavior is the same.
What is the difference between the two cases, if any?
class Employee:
raise_amount = 1.04
def __init__(self ,first ,last ,pay ):
self.first = first
self.last = last
self.pay = pay
self.email = first+"."+last+"#company.com"
def apply_raise(self): #but this is not an attribute
self.pay = int(self.pay * self.raise_amount)
#or self.pay = int(self.pay * Employee.raise_amount)
I assume your are referring to the self.raise_amount. In the case where you have it as that python must first look for instance variable and if not found it looks for similarly named class variable and creates a copy of it as an instance variable and uses that. if you were to then change the self.raise amount it would only be for the instance and not for any other instance made from the class.
Try creating an instance of the class and use the apply_raise method on it. then try changing the raise_amount class variable to something like 2.0 and call the method on the instance again. what you should see is that the amount only goes up 1.04 times, not 2. that is because it used the instance value it created the first time you ran the method.
Note: original post was edited to change to use the Class name for the raise amount. This post was a reply while it was self.raise_amount.
The lookup for the expression self.raise_amount can be complicated in general, be we can simplify it knowing that there are no methods or descriptors involved.
If self has an instance attribute named raise_amount, the value of that attribute is returned.
Otherwise, we start looking for class attributes, starting with the immediate type of self, here Employee. Since Employee.raise_amount is defined, we get that value...
... but what if Employee.raise_amount hadn't been defined? We would have moved on to the next class in the method resolution order of Employee, namely object. Since object.raise_amount is not defined, an AttributeError would have been raised.
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 5 years ago.
Improve this question
I want to create a service class that just has one instance, so should I make that class a singleton, or should I make the methods as classmethods?
class PromoService():
#classmethod
def create_promo(cls, promotion):
#do stuff
return promo
class DiscountPromoService(PromoService):
#classmethod
def create_promo(cls, promo, discount):
promo = super(DiscountPromoService, cls).create_promo(promo)
promo.discount = discount
promo.save()
return promo
The reason I don't want to create it as a module is because I would need to subclass my service. What is the most pythonic way to do this, the above-mentioned way or to make a singleton class?
Short answer: In my opinion it would work.
BUT, In pure pattern's sense, I have been wrestling with this question for a while:
Do python class methods and class attributes essentially behave like a Singleton?
All instances of that class have no bearing on them
Only class itself have access to them
There is always one of them
Yes, pure Singleton Pattern comparison would fail plain and simple but surely its not far off?
Wouldn't call myself a python expert, so happy to know views on this be corrected on my assumptions.
If you want a singleton, go with a singleton. The pattern referenced here works well. You would simply need to do something like:
class PromoService():
__metaclass__ = Singleton
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 years ago.
Improve this question
I am now trying to properly learn Python, and I am really puzzled by existence of two ways to create object properties: using the #property decorator and the property() method. So both of the following are valid:
class MyClassAt:
def __init__(self, value):
self._time = value
#property
def time(self):
return self._time
#time.setter
def time(self, value):
if value > 0:
self._time = value
else:
raise ValueError('Time should be positive')
and
class MyClassNoAt:
def __init__(self, value):
self._time = value
def get_time(self):
return self._time
def set_time(self, value):
if value > 0:
self._time = value
else:
raise ValueError('Time should be positive')
time = property(fget=get_time, fset=set_time)
Is there an agreement which one to use? What would a Pythonista choose?
They are equivalent, but the first one is preferred as many people find it more readable (while also not cluttering the code and the namespace).
The problem with the second method is that you are defining two methods that you will never use, and they remain in the class.
One would use the second method only if they have to support a very old Python version, which does not support decorators syntactic sugar. Function and method decorators were added in Python 2.4 (while class decorators only in version 2.6), so that is in almost all cases a problem of the past.
In the old days (pre python 2.4), the decorator syntax (i.e. #property) didn't exist yet, so the only way to create decorated functions was to use your second method
time = property(fget=get_time, fset=set_time)
The PEP that lead to decorators gives many reasons for the motivation behind the newer syntax, but perhaps the most important is this one.
The current method of applying a transformation to a function or
method places the actual transformation after the function body. For
large functions this separates a key component of the function's
behavior from the definition of the rest of the function's external
interface.
It's much clearer with the newer # syntax that a property exists by simply skimming through the code and looking at the method/property definitions.
Unfortunately, when they first added the new #property decorator, it only worked for decorating a getter. If you had a setter or a deleter function, you still had to use the old syntax.
Luckily, in Python 2.6, they added the getter, setter, and deleter attributes to properties so you could use the new syntax for all of them.
These days, there's really no reason to ever use the old syntax for decorating functions and classes.
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 8 years ago.
Improve this question
I need to add an object, e.g. Person, to a list that is given as a parameter. This is an example of the code
class Person:
def __init__(self, age):
self.age = age
def add_to_list(self, list_of_persons):
list_of_persons.append(self)
I know this situation may be caused by bad code design, however, it is working on a small test that I implemented. My question is, will this design cause issues in future? If yes, which ones?
I don't like your solution for various reasons, which include:
Elements should not be responsible for their membership in a container. It should be the container responsibility to add and remove then.
You generally don't expect methods to only modify the parameter. Methods are generally used to modify the instance, possibly, with some side-effects on the parameters, but I wouldn't expect a method to only change the parameter.
The method doesn't add any real functionality except that it hides how Person is inserted into a list. If you follow this design why didn't you, for example, add a method to remove a Person from the list?
I find:
person.add_to_list(people)
Quite unreadable.
If you think you aren't going to change the container for the Person, i.e. you will always use a list instead, why don't you simply use a list directly? It's simpler, has less overhead and makes you write less code:
people = []
people.append(Person(18))
If you think that you are probably going to change the container used, then I believe it's better to write a People class with an add and a remove method (and whatever else you need). Behind the scenes People can use whatever container it wants to implement these methods. In this way you get a readable, intuitive and robust design:
class People(object):
def __init__(self, people=()):
self._members = list(people)
# add other methods/special methods like __len__ etc.
def add(self, person):
self._members.append(person)
def remove(self, person):
self._members.remove(person)
people = People()
people.add(john)
people.add(jack)
# Change list to set?
class People(object):
def __init__(self, people=()):
self._members = set(people)
def add(self, person):
self._members.add(person)
def remove(self, person):
self._members.remove(person)
I can't really think of a situation where you couldn't replace a call to your person.add_to_list(list) with a list.append(person) call.
The problem here is that you are adding a dependency between your class Person and the list object that hurts encapsulation. If later you want to replace the list with another data structure that doesn't feature the "append" method (such as a custom container), you'll have to add another method Person.add_to_container to retain consistency, or add a append method to your other data structure (if you can and if this makes sense).