So I was looking at a certain class which has the following property function. However, the property method itself doesn't describe the procedure but instead calls another function to do so as follows:
class Foo():
#property
def params(self):
return self._params()
#property
def target(self):
return self._target()
def _params(self):
return print("hello")
def _target(self):
return print("world")
What I am trying to understand if it is some sort of pattern? I have seen a similar thing in another class as well where the method with property decorator simply calls another method of same name with underscore in the beginning.
Note: I do know what is property decorator but don't understand why this specific way of underscoring aims to achieve.
Effectively, the property is being used as a shortcut for calling a method with a fixed set of arguments. As a slightly different example, consider
class Foo():
#property
def params(self):
return self._params(1, "foo", True)
def _params(self, x, y, z):
...
f = Foo()
Now, f.params is a shortcut for f._params(1, "foo", True). Whether that is worth doing depends on whether _params is used for anything other than implementing the body of the params getter. If it isn't, there's little real point in writing code like this.
Related
I am new to opp programming.I wanted to know what to do with a function that is inside the class but does not use self value
For example
class example:
def __init__(self,n):
self.number=n
def get_t(self,t):
return t*t
def main(self):
b=1
k=self.get_t(b)
From the example the function get_t has nothing to do with self value.
So I wanted to know where to place the function get_t or may be how to restructure the class.
Thank you for your consideration
What you're looking for are static methods. To declare a method static do it like this
#staticmethod
def foo():
pass
Nothing. Just let it be, Python won't complain about it and there's nothing fundamentally wrong about methods that doesn't use its instance. If your linter complains about it, you can shut up that warning. These kind of helper functions are often intended to be private methods that aren't intended to be used externally, you may want to prefix the name with underscore to indicate that.
Convert it into a free function. Python is an OOP language, but it's also a mixed paradigm language, unlike Java, for example, you can actually create a function outside of a class declaration. Pythonic code does not necessarily means putting everything into classes, and often a free function is perfectly suitable place for functions that doesn't involve a particular object instance.
def get_t(t):
return t*t
class example:
def main(self):
b=1
k=self.get_t(b)
If you want to be able to call it from the class by doing Example.get_t(blah) without having to have an instance, then you can either use the staticmethod or classmethod decorator. I suggest using classmethod which can do everything that staticmethod can do while the reverse isn't true and it's easier to make classmethod work correctly when you need to override it in a multi inheritance situation. staticmethod has a very tiny performance advantage, but you're microoptimizing if that's your concern.
class example:
#classmethod
def get_t(cls, t):
return t*t
def main(self):
b=1
k=self.get_t(b)
If get_t() is only being called from one method, you can put it as an inner function of that method:
class example:
def main(self):
def get_t(t):
return t * t
b=1
k=self.get_t(b)
With regards to naming, get_xxx is usually a code smell in python. The get_ prefix indicates that the method is likely a getter, and pythonic code usually don't use getters/setters, because the language supports property. What you have on here though, isn't actually a getter but rather a computation method, so it shouldn't be prefixed with get_. A better name might be calculate_t(t) or square(t).
Case 1: If self is there:-
class example:
def get_t(self,t):
return t*t
Then You can not access get_t function directly from class example like example.get_t(t=2) ,it will give you error. But you can access now by creating an object of class like q = example() and then q.get_t(t=2) , it will give you your desired result.
Case 2 : If self is not there:-
class example:
def get_t(t):
return t*t
Now You can directly access get_t function by class example like example.get_t(t=2) ,it will give you your desired result. But now you cannot use get_t function by creating object like q = example() then q.get_t(t=2) it will give you error.
Conclusion :- It all depends on your use case. But when you struck in this type of ambiguity use #staticmethod like given below:-
class example:
#staticmethod
def get_t(t):
return t*t
I hope it may help you.
I'd like to write a decorator that does somewhat different things when it gets a function or a method.
for example, I'd like to write a cache decorator but I don't want to have self as part of the key if it's a method.
def cached(f):
def _internal(*args, **kwargs):
if ismethod(f):
key = create_key(*args[1:], **kwargs) # ignore self from args
else: # this is a regular function
key = create_key(*args, **kwargs)
return actual_cache_mechanism(key, f, *args, **kwargs)
return _internal
class A:
#cached
def b(self, something):
...
#cached
def c(something):
...
the problem is that when #cached is called, it cannot distinguish between methods and functions as both are of type function.
can that even be done? As I'm thinking of it I feel that actually methods have no idea about the context in which they are being defined in...
Thanks!
This is kind of an ugly hack, but you can use obj.__qualname__ to see if obj was defined in a class, by checking if it has a period
if "." in obj.__qualname__":
#obj is a member of an object, so it is a method
I'm not sure if it will work nicely for decorators though, since for this to work the method would need to be defined in the class.
I think it is desirable to avoid such introspecting decorator in the name of good pythonic style.
You can always factor out the function to be cached to accept just the required arguments:
#cached
def func(something):
return ...
class A:
def b(self, something):
self.bvalue = func(something)
For the case mentioned in comments (an object is needed to get the result, but its value does not affect it, e.g. a socket), please refer to these questions: How to ignore a parameter in functools. lru_cache? and Make #lru_cache ignore some of the function arguments
Let's start with this:
class Example(object):
change_docstring = True
#add_to_docstring(" (additional content!)")
def example_method(self):
"""Example docstring."""
pass
What I am trying to do is allow the #add_to_docstring decorator to append its parameter string to the docstring of the method only if the change_docstring attribute is True. I do not want to pass anything else into the decorator.
This solution works, but it is not exactly what I'm looking for.
def add_to_docstring(text):
def decorator(original_method):
def wrapper(self):
"""wrapper docstring."""
wrapper.__doc__ = original_method.__doc__
if self.change_docstring:
wrapper.__doc__ += text
return original_method(self)
return wrapper
return decorator
Let me explain.
The above solution only changes the docstring if example_method is executed. The docstring does not change when the class, method, etc. is loaded.
>>> Example.example_method.__doc__
"wrapper docstring."
>>>
>>> Example().example_method()
>>> Example.example_method.__doc__
"Example docstring. (additional content!)"
This is what I would like the output of the above command to be:
>>> Example.example_method.__doc__
"Example docstring. (additional content!)"
Again, I do not want to pass anything else into the decorator.
Update
For additional clarification, this is to allow for a decorator to change the docstring of a method, and to have that change be reflected in Sphinx generated documentation. Sphinx loads everything and gathers docstrings, but it does not do anything more.
Based on the selected solution, I added a module variable in the decorators module and exposed a method to disable the docstring change feature in the decorators. In order to disable the feature universally, I then called that disable function within my Sphinx conf.py files like so:
# import the decorators module
from some_modules import decorators
# disable the docstring change feature
decorators.disable_docstring_change()
Then the decorator can be used on any method in the project and the docstring changes will be either enabled or disabled.
As mentioned in Martijn Pieter's answer to "Accessing class variables from a list comprehension in the class definition" you cannot access class attributes if you're inside a new scope in the class. That answer mainly focuses on comprehensions and generator expressions in the class scope, but the same applies to ordinary functions, including decorators.
A simple way around this is to make change_docstring a global, and define it just before the class so that you can easily set it on a class by class basis. Another option is to make it an argument of the decorator, but you said you'd prefer not to do that. Here's a short demo that works on both Python 2 & 3.
def add_to_docstring(text):
def decorator(original_method):
def wrapper(self):
return original_method(self)
wrapper.__doc__ = original_method.__doc__
if change_docstring:
wrapper.__doc__ += text
return wrapper
return decorator
change_docstring = True
class Example(object):
#add_to_docstring(" (additional content!)")
def example_method(self):
"""Example docstring."""
pass
change_docstring = False
class Other(object):
#add_to_docstring(" (more content!)")
def example_method(self):
"""Other docstring."""
pass
print(Example.example_method.__doc__)
print(Other.example_method.__doc__)
output
Example docstring. (additional content!)
Other docstring.
Decorate and tag the methods
We don't need to care about much here for function signatures, whether it's bound or unbound - we just put an attribute with the additional text on the function object whatever it is.
def add_to_docstring(text):
def func(f):
f.__add_to_docstring = text
return f
return func
Decorate the class to indicate we want tagged methods to be honoured
By using a class decorator we can indicate we wish to honour the tagged methods and change the docstrings. We scan over the callable objects, check if they're decorated objects that contain something to add to the docstring and make the appropriate changes before returning a new type with different function docstrings.
def change_docstrings(cls):
for obj in vars(cls).values():
if callable(obj) and hasattr(obj, '__add_to_docstring'):
obj.__doc__ = (obj.__doc__ or '') + obj.__add_to_docstring
del obj.__add_to_docstring
return cls
Putting that together
#change_docstrings
class Example:
#add_to_docstring('(cabbage!)')
def example(self):
""" something here """
pass
Checking Example.example.__doc__ we get - ' something here (cabbage!)' and if you remove the #change_docstrings class decorator - you get no changes.
Note that this moves the change_docstrings out of the class and to whether you decorate or not, however, it allows a construct such as:
unchanged_docstrings = Example
changed_docstrings = change_docstrings(Example)
I keep seeing the following decorators used: #staticmethod, #property for example:
#staticmethod
def add_url():
return reverse('add_user')
#property
def password_not_expired(self):
return not self.password_expired
Could someone explain when to use one over the other? Say I want to add this code:
def get_user_type(self):
return self.user_type
I would use a #staticmethod method right?
You can't use self in a #staticmethod. Because the only thing #staticmethod does is make the function not be passed self. Look in your own example: add_url doesn't take a self argument.
"static" here is in the entirely misleading sense of how C++ and Java use it. A Python #staticmethod is really just a regular function that happens to live in a class, nothing to do with whether values are changed.
You can use #property without writing a setter. In fact, that's probably the most common way to use it.
In Dive Into Python, Mark Pilgrim says that:
When defining your class methods, you must explicitly list self as the first argument for each method
He then gives a few examples of this in code:
def clear(self): self.data.clear()
def copy(self):
if self.__class__ is UserDict:
return UserDict(self.data)
import copy
return copy.copy(self)
While going through some Python code online, I came across the #classmethod decorator. An example of that is:
class Logger:
#classmethod
def debug(msg):
print "DEBUG: " + msg
(Notice that there is no self parameter in the debug function)
Is there any difference in defining class methods using self as the first parameter and using the #classmethod decorator? If not, is one way of defining class methods more commonly used/preferred over another?
#classmethod isn't the same as defining an instance method. Functions defined with #classmethod receive the class as the first argument, as opposed to an instance method which receives a specific instance. See the Python docs here for more information.
self is not and will never will be implicit.
"self will not become implicit.
Having self be explicit is a good thing. It makes the code clear by removing ambiguity about how a variable resolves. It also makes the difference between functions and methods small."
http://www.python.org/dev/peps/pep-3099/