2013-07-09 2 views
5

Я очень новичок в программировании и начал изучать питон. Можете выглядеть очень глупым вопросом, поэтому, пожалуйста, простите мое невежество. Рассмотрим следующий фрагмент кода:Понимание атрибутов класса python

class Test1: 
    bar = 10  
    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 
    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80 

if __name__ == '__main__': 
    test1 = Test1() 
    test1.display(80) 
    test1.display1() 
    print test1.bar #10 
    print test1.foo #80 

Я хочу, чтобы понять, в чем разница между использованием Foo и бар (ВПР, где мы определили их), как в рамках мудрыми они одинаково доступны во всех местах по сравнению с друг друга, и только разница в том, что внутри есть функция, а другая - внутри класса, но оба они все еще являются «экземплярами». Так что это хорошая практика?

Кроме того, если я немного изменить функцию отображения, как показано ниже:

def display(self,foo): 
     self.foo=foo 
     foo = foo 
     print "self.foo : ",self.foo 
     print "foo : ",foo 

Может кто-то пожалуйста, объясните, как питон видит это, как и в чем разница/значение этого ключевого слова self приносящей между двумя foo.

+4

Нет, 'bar' является * не * переменной экземпляра. Эти два очень разные, поэтому речь идет не о «хорошей практике». Речь идет о том, что подходит для вашей ситуации, потому что они служат различным целям. – phant0m

+1

Также 'self.bar' работает, потому что имя' bar' сначала выполняется в пространстве имен экземпляра, а затем в классе. Тот факт, что 'self.bar' работает, не всегда * означает, что' bar' является переменной экземпляра. – ersran9

ответ

3

bar является атрибутом класса. так как классы в Python - это объекты, они тоже могут иметь атрибуты. bar просто живет на этом объекте Test, а не на его экземпляре.

Из-за того, как Python разрешает поиск атрибутов, он выглядит так: test1 имеет атрибут bar, но это не так.

foo с другой стороны живет на экземпляре test1 после звонка display(80). Это означает, что разные экземпляры Test могут иметь разные значения в своих соответствующих атрибутах foo.

Конечно, вы могли бы использовать переменные класса как «общее значение по умолчанию», которое вы можете «переопределить» атрибутом экземпляра, но это может запутать.

Второй вопрос

def display(self,foo): 
    self.foo=foo 
    foo = foo 
    print "self.foo : ",self.foo 
    print "foo : ",foo 

Давайте просто получить деталь из пути: self не является ключевым словом, это просто условность назвать первый аргумент «я», вы могли бы также назвать его «это «или« тот »или« бар », если хотите, но я бы не рекомендовал этого.

Python передаст объект, по которому метод был вызван как первый аргумент.

def display(self,foo): 

Это foo - это имя первого параметра функции экземпляра дисплея.

self.foo=foo 

Это устанавливает атрибут с именем «Foo» экземпляр, на котором вы назвали display() к значению, которое вы передали в качестве первого аргумента. Используя ваш пример test1.display(80), self будет test1, foo будет 80 и test1.foo, таким образом, будет установлено значение 80.

foo = foo 

Это не делает ничего. Он ссылается на первый параметр foo.

Следующие две строки снова ссылаются на переменную экземпляра foo и первый параметр foo.

4

bar - это атрибут класса, а foo - атрибут экземпляра. Основное отличие заключается в том, что bar будет доступен для всех экземпляров класса в то время как foo будут доступны к примеру, только если вы звоните дисплей на этом экземпляре

>>> ins1 = Test1() 

ins1.bar прекрасно работает, потому что это атрибут класса и разделяют все экземпляров.

>>> ins1.bar 
10 

Но вы не можете получить доступ к Foo прямо здесь, как это еще не определено:

>>> ins1.foo 
Traceback (most recent call last): 
    File "<ipython-input-62-9495b4da308f>", line 1, in <module> 
    ins1.foo 
AttributeError: Test1 instance has no attribute 'foo' 

>>> ins1.display(12) 
foo : 12 
>>> ins1.foo 
12 

Если вы хотите инициализировать некоторые атрибуты экземпляра, когда экземпляр создается затем поместить их внутри метода __init__ ,

class A(object): 
    bar = 10 
    def __init__(self, foo): 
     self.foo = foo #this gets initialized when the instance is created 
    def func(self, x): 
     self.spam = x #this will be available only when you call func() on the instance 
...   
>>> a = A(10) 
>>> a.bar 
10 
>>> a.foo 
10 
>>> a.spam 
Traceback (most recent call last): 
    File "<ipython-input-85-3b4ed07da1b4>", line 1, in <module> 
    a.spam 
AttributeError: 'A' object has no attribute 'spam' 

>>> a.func(2) 
>>> a.spam 
2 
+1

Я думаю, что * главная * разница в том, что атрибут класса является «общим», а не доступен для всех экземпляров. – phant0m

1

Лично мне не нравится определение переменных экземпляра внутри отличных __init__ или как переменные класса, как bar в вашем примере выше методов.

Снова, лично, мне нравится видеть каждого члена моего класса, глядя на верх. Является ли это переменной класса, которую вы используете в качестве переменной экземпляра (что-то, что я обычно не делаю) или переменной экземпляра, определенной в __init__, легко определить, что есть и не определено в классе, путем проверки первого раздела определения класса.

Если вам не нужен доступ к переменной как члену класса (т. Е. Вы определяете ее там, чтобы избежать записи self.variable = val в методе __init__, то я бы избежал ее. Если вам может потребоваться доступ это как переменная класса, то делать то, что вы с bar нормально в моей книге.

Это будет мой предпочтительный способ написания вам класс.

class Test1: 

    def __init__(self): 
     self.foo = None 
     self.bar = 10 

    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 

    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80 
Смежные вопросы