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.
Related
This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 6 months ago.
When defining a method on a class in Python, it looks something like this:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
But in some other languages, such as C#, you have a reference to the object that the method is bound to with the "this" keyword without declaring it as an argument in the method prototype.
Was this an intentional language design decision in Python or are there some implementation details that require the passing of "self" as an argument?
I like to quote Peters' Zen of Python. "Explicit is better than implicit."
In Java and C++, 'this.' can be deduced, except when you have variable names that make it impossible to deduce. So you sometimes need it and sometimes don't.
Python elects to make things like this explicit rather than based on a rule.
Additionally, since nothing is implied or assumed, parts of the implementation are exposed. self.__class__, self.__dict__ and other "internal" structures are available in an obvious way.
It's to minimize the difference between methods and functions. It allows you to easily generate methods in metaclasses, or add methods at runtime to pre-existing classes.
e.g.
>>> class C:
... def foo(self):
... print("Hi!")
...
>>>
>>> def bar(self):
... print("Bork bork bork!")
...
>>>
>>> c = C()
>>> C.bar = bar
>>> c.bar()
Bork bork bork!
>>> c.foo()
Hi!
>>>
It also (as far as I know) makes the implementation of the python runtime easier.
I suggest that one should read Guido van Rossum's blog on this topic - Why explicit self has to stay.
When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '#classmethod' or '#staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not.
I reject hacks like special-casing '#classmethod' and '#staticmethod'.
Python doesn't force you on using "self". You can give it whatever name you want. You just have to remember that the first argument in a method definition header is a reference to the object.
Also allows you to do this: (in short, invoking Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5) will return 12, but will do so in the craziest of ways.
class Outer(object):
def __init__(self, outer_num):
self.outer_num = outer_num
def create_inner_class(outer_self, inner_arg):
class Inner(object):
inner_arg = inner_arg
def weird_sum_with_closure_scope(inner_self, num)
return num + outer_self.outer_num + inner_arg
return Inner
Of course, this is harder to imagine in languages like Java and C#. By making the self reference explicit, you're free to refer to any object by that self reference. Also, such a way of playing with classes at runtime is harder to do in the more static languages - not that's it's necessarily good or bad. It's just that the explicit self allows all this craziness to exist.
Moreover, imagine this: We'd like to customize the behavior of methods (for profiling, or some crazy black magic). This can lead us to think: what if we had a class Method whose behavior we could override or control?
Well here it is:
from functools import partial
class MagicMethod(object):
"""Does black magic when called"""
def __get__(self, obj, obj_type):
# This binds the <other> class instance to the <innocent_self> parameter
# of the method MagicMethod.invoke
return partial(self.invoke, obj)
def invoke(magic_self, innocent_self, *args, **kwargs):
# do black magic here
...
print magic_self, innocent_self, args, kwargs
class InnocentClass(object):
magic_method = MagicMethod()
And now: InnocentClass().magic_method() will act like expected. The method will be bound with the innocent_self parameter to InnocentClass, and with the magic_self to the MagicMethod instance. Weird huh? It's like having 2 keywords this1 and this2 in languages like Java and C#. Magic like this allows frameworks to do stuff that would otherwise be much more verbose.
Again, I don't want to comment on the ethics of this stuff. I just wanted to show things that would be harder to do without an explicit self reference.
I think it has to do with PEP 227:
Names in class scope are not accessible. Names are resolved in the
innermost enclosing function scope. If a class definition occurs in a
chain of nested scopes, the resolution process skips class
definitions. This rule prevents odd interactions between class
attributes and local variable access. If a name binding operation
occurs in a class definition, it creates an attribute on the resulting
class object. To access this variable in a method, or in a function
nested within a method, an attribute reference must be used, either
via self or via the class name.
I think the real reason besides "The Zen of Python" is that Functions are first class citizens in Python.
Which essentially makes them an Object. Now The fundamental issue is if your functions are object as well then, in Object oriented paradigm how would you send messages to Objects when the messages themselves are objects ?
Looks like a chicken egg problem, to reduce this paradox, the only possible way is to either pass a context of execution to methods or detect it. But since python can have nested functions it would be impossible to do so as the context of execution would change for inner functions.
This means the only possible solution is to explicitly pass 'self' (The context of execution).
So i believe it is a implementation problem the Zen came much later.
As explained in self in Python, Demystified
anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit). This is the reason the first parameter of a function in class must be the object itself.
class Point(object):
def __init__(self,x = 0,y = 0):
self.x = x
self.y = y
def distance(self):
"""Find distance from origin"""
return (self.x**2 + self.y**2) ** 0.5
Invocations:
>>> p1 = Point(6,8)
>>> p1.distance()
10.0
init() defines three parameters but we just passed two (6 and 8). Similarly distance() requires one but zero arguments were passed.
Why is Python not complaining about this argument number mismatch?
Generally, when we call a method with some arguments, the corresponding class function is called by placing the method's object before the first argument. So, anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit).
This is the reason the first parameter of a function in class must be the object itself. Writing this parameter as self is merely a convention. It is not a keyword and has no special meaning in Python. We could use other names (like this) but I strongly suggest you not to. Using names other than self is frowned upon by most developers and degrades the readability of the code ("Readability counts").
...
In, the first example self.x is an instance attribute whereas x is a local variable. They are not the same and lie in different namespaces.
Self Is Here To Stay
Many have proposed to make self a keyword in Python, like this in C++ and Java. This would eliminate the redundant use of explicit self from the formal parameter list in methods. While this idea seems promising, it's not going to happen. At least not in the near future. The main reason is backward compatibility. Here is a blog from the creator of Python himself explaining why the explicit self has to stay.
The 'self' parameter keeps the current calling object.
class class_name:
class_variable
def method_name(self,arg):
self.var=arg
obj=class_name()
obj.method_name()
here, the self argument holds the object obj. Hence, the statement self.var denotes obj.var
There is also another very simple answer: according to the zen of python, "explicit is better than implicit".
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
I've been trying to learn classes and i struggle to see when they can become useful. In this example with employees i find using a well organized multi-dimensional list to be easier.
I've provided examples of what i mean with a 2 sets of code that does the exact same thing using lists and classes.
I have tried watching many youtube tutorials on classes but i just can't seem to understand why a multi-dimensional list wouldn't do the job better.
class Employees():
def __init__(self, First_Name, Last_Name, pay = "26000"):
self.First_Name = First_Name
self.Last_Name = Last_Name
self.pay = pay
def greeting(self):
return "Hi, my name is "+self.First_Name+" "+self.Last_Name+" and I earn: "+self.pay
employee_1 = Employees("First_Name_1", "Last_Name_1", "30000")
employee_2 = Employees("First_Name_2", "Last_Name_2")
print(employee_1.greeting())
print(employee_2.greeting())
employee_list = []
def employees(employee_list, First_Name, Last_Name, pay = "26000"):
employee_list += [[First_Name, Last_Name, pay, lambda: greeting(First_Name, Last_Name, pay)]]
def greeting(a, b, c):
return "Hi, my name is "+a+" "+b+" and I earn: "+c
employees(employee_list, "First_Name_1", "Last_Name_1", "30000")
employees(employee_list, "First_Name_2", "Last_Name_2")
print(employee_list[0][3]())
print(employee_list[1][3]())
Classes are much, much more organized and useful than lists. For instance, classes have constructors, methods, attributes, magic methods, superclasses, etc. Classes are most useful when you have a lot of related functions and when you want to create more than one object. They can immensely help with organizing spaghetti code, especially when used with modules. Additionally, many libraries use classes rather than lists.
This is a tenet of Object-Oriented Programming; you're encapsulating your data into classes as opposed to having them declared in a more procedural and ad-hoc fashion.
The immediate advantage is that the first code block is way more readable and its intentions are a lot clearer. You have Employees and you know that you want to print the greetings of them. With the second code block, you have a list which requires you to keep track of where each value is and it's not immediately apparent what employee_list[0][3] represents. It also becomes tough to refactor or fix if the order of your list changes for any reason.
Defining a class provides a convenient syntax for working with data, but it doesn't provide much you couldn't simulate. Consider a slightly different reworking of your list example:
# Employees.__init__
# Instead of named attributes, there are implied positions in a list
# 0 - first name
# 1 - last name
# 2 - salary
def make_employee(first, last, pay="26000"):
return [first, last, pay]
# Employees.greeting
def greeting(employee):
first, last, pay = employee
return "Hi, my name is {} {} and I earn {}".format(first, last, pay)
# Call make_employee instead of Employees
employee1 = make_employee("First_Name_1", "Last_Name_1", "30000")
employee1 = make_employee("First_Name_2", "Last_Name_2")
# Pass employee "objects" to greeting
print(greeting(employee1))
print(greeting(employee2))
Support for inheritance aside, the only real difference here is that you pass an employee "object" explicitly to a function, rather than invoking a method on an object.
Inheritance and namespacing (multiple classes can have a method named greeting without them interfering with each other) are two big advantages to using classes, though.
A class provides better readability and a better abstraction, i.e. you could inherit properties (variables/functions) for a 'dog' from class 'pet'.
Normally a class is better style as it can clean up 'spaghetti' code.
Classes are types and lists are already a built-in type with a constructor and methods (e.g. .sort). So the questions should be whether a type (or class) is sufficient for what you are doing or whether you want to have extra (different) behavior.
You can even extend the list type to your own version and change the behavior and add methods just like this and maintain all the ones that are already there:
class MyList(list):
def my_method(self):
pass
In a more general picture, whether you should use classes or not (functional style) is a matter of taste and philosophy. The big advantage of classes (maintaining state) can also be there biggest pitfall (side effects if not carefully crafted).
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 9 days ago.
The community is reviewing whether to reopen this question as of 9 days ago.
Improve this question
I have Python classes, of which I need only one instance at runtime, so it would be sufficient to have the attributes only once per class and not per instance. If there would be more than one instance (which won't happen), all instance should have the same configuration. I wonder which of the following options would be better or more "idiomatic" Python.
Class variables:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Instance variables:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
If you have only one instance anyway, it's best to make all variables per-instance, simply because they will be accessed (a little bit) faster (one less level of "lookup" due to the "inheritance" from class to instance), and there are no downsides to weigh against this small advantage.
Further echoing Mike's and Alex's advice and adding my own color...
Using instance attributes are the typical... the more idiomatic Python. Class attributes are not used used as much, since their use cases are specific. The same is true for static and class methods vs. "normal" methods. They're special constructs addressing specific use cases, else it's code created by an aberrant programmer wanting to show off they know some obscure corner of Python programming.
Alex mentions in his reply that access will be (a little bit) faster due to one less level of lookup... let me further clarify for those who don't know about how this works yet. It is very similar to variable access -- the search order of which is:
locals
nonlocals
globals
built-ins
For attribute access, the order is:
instance
class
base classes as determined by the MRO (method resolution order)
Both techniques work in an "inside-out" manner, meaning the most local objects are checked first, then outer layers are checked in succession.
In your example above, let's say you're looking up the path attribute. When it encounters a reference like "self.path", Python will look at the instance attributes first for a match. When that fails, it checks the class from which the object was instantiated from. Finally, it will search the base classes. As Alex stated, if your attribute is found in the instance, it doesn't need to look elsewhere, hence your little bit of time savings.
However, if you insist on class attributes, you need that extra lookup. Or, your other alternative is to refer to the object via the class instead of the instance, e.g., MyController.path instead of self.path. That's a direct lookup which will get around the deferred lookup, but as alex mentions below, it's a global variable, so you lose that bit that you thought you were going to save (unless you create a local reference to the [global] class name).
The bottom-line is that you should use instance attributes most of the time. However, there will be occasions where a class attribute is the right tool for the job. Code using both at the same time will require the most diligence, because using self will only get you the instance attribute object and shadows access to the class attribute of the same name. In this case, you must use access the attribute by the class name in order to reference it.
When in doubt, you probably want an instance attribute.
Class attributes are best reserved for special cases where they make sense. The only very-common use case is methods. It isn't uncommon to use class attributes for read-only constants that instances need to know (though the only benefit to this is if you also want access from outside the class), but you should certainly be cautious about storing any state in them, which is seldom what you want. Even if you will only have one instance, you should write the class like you would any other, which usually means using instance attributes.
Same question at Performance of accessing class variables in Python - the code here adapted from #Edward Loper
Local Variables are the fastest to access, pretty much tied with Module Variables, followed by Class Variables, followed by Instance Variables.
There are 4 scopes you can access variables from:
Instance Variables (self.varname)
Class Variables (Classname.varname)
Module Variables (VARNAME)
Local Variables (varname)
The test:
import timeit
setup='''
XGLOBAL= 5
class A:
xclass = 5
def __init__(self):
self.xinstance = 5
def f1(self):
xlocal = 5
x = self.xinstance
def f2(self):
xlocal = 5
x = A.xclass
def f3(self):
xlocal = 5
x = XGLOBAL
def f4(self):
xlocal = 5
x = xlocal
a = A()
'''
print('access via instance variable: %.3f' % timeit.timeit('a.f1()', setup=setup, number=300000000) )
print('access via class variable: %.3f' % timeit.timeit('a.f2()', setup=setup, number=300000000) )
print('access via module variable: %.3f' % timeit.timeit('a.f3()', setup=setup, number=300000000) )
print('access via local variable: %.3f' % timeit.timeit('a.f4()', setup=setup, number=300000000) )
The result:
access via instance variable: 93.456
access via class variable: 82.169
access via module variable: 72.634
access via local variable: 72.199
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 9 days ago.
The community is reviewing whether to reopen this question as of 9 days ago.
Improve this question
I have Python classes, of which I need only one instance at runtime, so it would be sufficient to have the attributes only once per class and not per instance. If there would be more than one instance (which won't happen), all instance should have the same configuration. I wonder which of the following options would be better or more "idiomatic" Python.
Class variables:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Instance variables:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
If you have only one instance anyway, it's best to make all variables per-instance, simply because they will be accessed (a little bit) faster (one less level of "lookup" due to the "inheritance" from class to instance), and there are no downsides to weigh against this small advantage.
Further echoing Mike's and Alex's advice and adding my own color...
Using instance attributes are the typical... the more idiomatic Python. Class attributes are not used used as much, since their use cases are specific. The same is true for static and class methods vs. "normal" methods. They're special constructs addressing specific use cases, else it's code created by an aberrant programmer wanting to show off they know some obscure corner of Python programming.
Alex mentions in his reply that access will be (a little bit) faster due to one less level of lookup... let me further clarify for those who don't know about how this works yet. It is very similar to variable access -- the search order of which is:
locals
nonlocals
globals
built-ins
For attribute access, the order is:
instance
class
base classes as determined by the MRO (method resolution order)
Both techniques work in an "inside-out" manner, meaning the most local objects are checked first, then outer layers are checked in succession.
In your example above, let's say you're looking up the path attribute. When it encounters a reference like "self.path", Python will look at the instance attributes first for a match. When that fails, it checks the class from which the object was instantiated from. Finally, it will search the base classes. As Alex stated, if your attribute is found in the instance, it doesn't need to look elsewhere, hence your little bit of time savings.
However, if you insist on class attributes, you need that extra lookup. Or, your other alternative is to refer to the object via the class instead of the instance, e.g., MyController.path instead of self.path. That's a direct lookup which will get around the deferred lookup, but as alex mentions below, it's a global variable, so you lose that bit that you thought you were going to save (unless you create a local reference to the [global] class name).
The bottom-line is that you should use instance attributes most of the time. However, there will be occasions where a class attribute is the right tool for the job. Code using both at the same time will require the most diligence, because using self will only get you the instance attribute object and shadows access to the class attribute of the same name. In this case, you must use access the attribute by the class name in order to reference it.
When in doubt, you probably want an instance attribute.
Class attributes are best reserved for special cases where they make sense. The only very-common use case is methods. It isn't uncommon to use class attributes for read-only constants that instances need to know (though the only benefit to this is if you also want access from outside the class), but you should certainly be cautious about storing any state in them, which is seldom what you want. Even if you will only have one instance, you should write the class like you would any other, which usually means using instance attributes.
Same question at Performance of accessing class variables in Python - the code here adapted from #Edward Loper
Local Variables are the fastest to access, pretty much tied with Module Variables, followed by Class Variables, followed by Instance Variables.
There are 4 scopes you can access variables from:
Instance Variables (self.varname)
Class Variables (Classname.varname)
Module Variables (VARNAME)
Local Variables (varname)
The test:
import timeit
setup='''
XGLOBAL= 5
class A:
xclass = 5
def __init__(self):
self.xinstance = 5
def f1(self):
xlocal = 5
x = self.xinstance
def f2(self):
xlocal = 5
x = A.xclass
def f3(self):
xlocal = 5
x = XGLOBAL
def f4(self):
xlocal = 5
x = xlocal
a = A()
'''
print('access via instance variable: %.3f' % timeit.timeit('a.f1()', setup=setup, number=300000000) )
print('access via class variable: %.3f' % timeit.timeit('a.f2()', setup=setup, number=300000000) )
print('access via module variable: %.3f' % timeit.timeit('a.f3()', setup=setup, number=300000000) )
print('access via local variable: %.3f' % timeit.timeit('a.f4()', setup=setup, number=300000000) )
The result:
access via instance variable: 93.456
access via class variable: 82.169
access via module variable: 72.634
access via local variable: 72.199
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).