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.
Related
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 4 months ago.
Improve this question
We are often told not to shadow builtins like id, int, list and so on. Is it ever acceptable to break this rule?
In general, you should not shadow builtins for several reasons:
doing so prevents you from using the builtin later by calling its common name
other people reading your code will be confused, as they expect list to be the builtin list, and so on
IDEs will (usually) compound this by highlighting your shadowed variables as though they were builtins.
However there are some exceptions.
In class attributes
Using a builtin name in a class attribute doesn't shadow anything at all at runtime, although it might at evaluation. This pattern is quite common:
class Foo:
def __init__(self, foo_id: int) -> None:
self.id = foo_id
Foo().id was unbound until we bound it in the constructor. No shadowing is going on here. The use of id to mean "identity" is sufficiently common that it is probably better than any alternative (like obj_id or identity), and nobody is going to expect Foo().id to be the builtin id.
If you use dataclasses, this might involve shadowing:
#dataclass
class Foo:
# id refers to the builtin `id`
id: int = 0 # assigning a default for the example
# id referes to `Foo.id`, which has the typehint int
foo = Foo(id="id of foo")
# foo.id refers to the *instance* id, which is actually a string.
In this example we do shadow id, briefly. We couldn't use it at evaluation time. But you probably shoudn't be getting the id of an object when defining (not constructing) a class anyhow. Because of the way dataclasses work, we end up with a separate id on the instance foo (which as is demonstrated here, doesn't even have to be the right type!). There are three namespaces at play: the enclosing namespace, in which id means what it normally does, the namespace of the unininstantised class Foo, in which id is 0, and the namespace of the object foo, in which id is a string. We have shadowed in the second of these, but we don't do anything in that namespace later anyhow.
In small functions, when clarity demands
It might be acceptable to shadow the a builtin in a small function which can never conceivably use the shadowed object, if doing so increases clarity. Both of these are probably fine:
def get_object_from_db(id: int) -> CustomObj:
...
def find_enclosing_dir(filename: str) -> Pathlib.Path:
f = _find_file(filename)
dir = f.parent
some_logic_to_validate(dir)
return dir
class Foo:
def __init__(self, id: int) -> None:
self.id = id
The first example shadows id in a function in which the only 'id' we care about is the database id for the data we're retrieving to build our CustomObj. Nevertheless, using obj_id here might well be clearer. The second example shadows dir and uses it for a directory. dir and similar introspection tools are very unlikely to be used in this code; again parent_dir might be clearer, but shadowing here is a stylistic choice. In the third example we shadow id in the constructor for Foo. Again, we cannot now use id, but our code is arguably cleaner.
After thinking twice
In general, avoiding shadowing is a good thing. Inside a small function or method it might make sense to shadow a builtin for clarity. This should only be done when it increases clarity, and the work of refactoring to avoid the shadowing if something changes down the line is tiny. At the very least the function should fit comfortably on one screen. Class attributes can 'shadow' with impunity (as they don't shadow at all), but only a few names open themselves up to being used like this. id and maybe dir make sense, but Foo.list or Foo.str is probably less clear than a descriptive name.
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 9 months ago.
Improve this question
I've been going through Python tutorial for Python properties and I can't make any sense of this code:
# using property class
class Celsius:
def __init__(self, temperature=0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
# getter
def get_temperature(self):
print("Getting value...")
return self._temperature
# setter
def set_temperature(self, value):
print("Setting value...")
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible")
self._temperature = value
# creating a property object
temperature = property(get_temperature, set_temperature)
human = Celsius(37)
print(human.temperature)
print(human.to_fahrenheit())
human.temperature = -300
Why is the property being assigned outside of init?
where is self._temperature even defined?
How is self._temperature is linked to self.temperature even though these two are not linked together any where in the code?
How is it that in the to_fahrenheit function, even though that I'm changing self.temperature, it is self._temperature that gets changed not the original temperature that is defined in the constructor?
I'd really appreciate any help since this does not make any sense but works!
Your snippet illustrates the concept of getter and setter methods in Python. When attempting to set the temperature class variable (e.g. human.temperature = -300), Python does not actually modify human.temperature, but calls human.set_temperature(-300) instead, which, given no error is raised, sets human._temperature to the specified value. Similarly, calling print(human.temperature) is equivalent to print(human.get_temperature()) (try these replacements in your code and see what happens).
Moreover, the _ prefix of _temperature signal that it is a private variable, i.e. should not be used outside the class definition and the get_ / set_ prefix declares that the function is a getter / setter.
In conclusion, human.temperature does not hold a value, but rather calls human.get_temperature() or human.set_temperature() depending on the context. The actual value is stored in human._temperature. For a more detailed explanation, I suggest reading the aforementioned articles.
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
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 4 years ago.
Improve this question
If I have an object, and within that object I've defined a variable, which of these methods would be considered 'best' for accessing the variable?
Method One
Using a getter function
class MyClass:
def __init__(self):
self.the_variable = 21 * 2
def get_the_variable(self):
return self.the_variable
if __name__ == "__main__"
a = MyClass()
print(a.get_the_variable())
Method Two
Using the #property decorator
class MyClass:
def __init__(self):
self._the_variable = 21 * 2
#property
def the_variable(self):
return self._the_variable
if __name__ == "__main__"
a = MyClass()
print(a.the_variable)
Method Three
Simply accessing it directly
class MyClass:
def __init__(self):
self.the_variable = 21 * 2
if __name__ == "__main__"
a = MyClass()
print(a.the_variable)
Are any of these methods more pythonic than the others?
Method 3 is the standard pythonic way to start. If you need additional logic, filtering or some other behavior for the attribute you can always go back and add a method for the attribute and use the #property decorator at a later time. That's the beauty of python, start with something simple that works. If you later need finer control over the attribute you can create the property and not have to update/change any of the client code that uses the attribute. The client code will not know the difference between accessing the attribute directly vs calling a method and as a result does not have to change.
This ideology is confirmed via PEP 549
Python's descriptor protocol guides programmers towards elegant API design. If your class supports a data-like member, and you might someday need to run code when changing the member's value, you're encouraged to simply declare it as a simple data member of the class for now. If in the future you do need to run code, you can change it to a "property", and happily the API doesn't change.
I think it's not easy to answer since it's based on the program.
class MyClass:
def __init__(self):
self.the_variable = 21 * 2
def get_the_variable(self):
return self.the_variable
But if you want to pass a class attirubete to some variable, I think it's better to use getter-setter, since it is more readable and understandable. Because you are basically telling I ask this value. For example:
if __name__ == "__main__":
a = MyClass()
modified_variable = a.get_the_variable() * 2
In contrary, if you are just using that class attribute, third option a.the_variable is better.
if a.get_the_variable() == 42:
# do something
else:
# do something
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).