In python, when self can be omitted?

不想你离开。 提交于 2021-01-21 11:27:09

问题


Codes below defined Duck class as composited from Bill class and Tail class. My questions is that as for the method about() inside Duck class definition, why can one write bill.description and tail.length? Is self omitted here? If yes, when can I omit self? Can I omit them inside __init__ method?

class Bill(): 
    def __init__(self, description):
        self.description = description 
class Tail(): 
    def __init__(self, length): 
        self.length = length 
class Duck(): 
    def __init__(self, bill, tail): 
        self.bill = bill
        self.tail = tail 
    def about(self): 
        print('This duck has a', bill.description, 'bill and a', tail.length, 'tail')
tail = Tail('long')
bill = Bill('wide orange') 
duck = Duck(bill, tail)
duck.about()

The output are as follows,


回答1:


To make a long story short: you MUST use self. whenever you want to access an attribute (data attribute, property or method) of the current instance.

For a somewhat more detailed answer: when using def in a class statement, what you create is not a "method" but a plain function. When looked up a class or instance attribute (Duck.about or duck.about) this function will be wrapped (together with the class and instance on which it's looked up) in a callable method object that will take care of automagically inject the instance (or class) object as first parameter to the function call. You can read the whole details here : https://wiki.python.org/moin/FromFunctionToMethod

As other already mentionned, your code snippet only accidentally "works" because it ends up looking global names that happens to be defined, and breaks as soon as these names are not defined:

# tail = Tail('long')
# bill = Bill('wide orange') 
duck = Duck(Bill('wide orange'), Tail('long'))
duck.about()

=> crashes with a NameError

You'd also get unexpected results if rebinding these global names ie:

tail = Tail('long')
bill = Bill('wide orange') 
duck1 = Duck(bill, tail)

tail = Tail('short')
bill = Bill('norvegian blue') 
duck2 = Duck(bill, tail)

duck1.about()

=> Duh, why does it prints "short norvegian blue" ???




回答2:


In Python explicit is better than implicit and self cannot ever be omitted when accessing member variables.

In your case you actually use names from global scope. To trigger an error simply assign the created objects to other names:

tail1 = Tail('long')
bill1 = Bill('another')
duck = Duck(tail1, bill1)
duck.about()



回答3:


You can write that because you have defined a global variable bill and tail, which is being referenced here.

...
    def about(self): 
        print('This duck has a', bill.description, 'bill and a', tail.length, 'tail')
                         # these ^^^^                            ^^^^

# refer to these vvvv
tail = Tail('long')
bill = Bill('wide orange') 

So it's not doing what you think. If you want to refer to the bill and tail properties of your current object, you cannot omit self, it has to be self.bill and self.tail. Your code will break if you rename or remove those global variables.




回答4:


You should avoid doing that. bill in about() will refer to bill in the outer scope, in this case the global one. So when you change the value of that global variable, the output of about() is also affected:

>>> tail = Tail('long')
>>> bill = Bill('wide orange')
>>> duck = Duck(bill, tail)
>>> duck.about()
This duck has a wide orange bill and a long tail
>>> bill = Bill('DIFFERENT')
>>> duck.about()
This duck has a DIFFERENT bill and a long tail

In order to reference the bill and tail objects that were passed to Duck() and are stored within the instance, you always need to use self.bill and self.tail.



来源:https://stackoverflow.com/questions/37963018/in-python-when-self-can-be-omitted

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!