Python _uu init__;()内部和外部变量之间的差异

Python _uu init__;()内部和外部变量之间的差异,python,class,oop,constructor,Python,Class,Oop,Constructor,除了名称之外,这些类之间还有什么区别吗 class WithClass (): def __init__(self): self.value = "Bob" def my_func(self): print(self.value) class WithoutClass (): value = "Bob" def my_func(self): print(self.value) 如果我使用或不使用\uuuu in

除了名称之外,这些类之间还有什么区别吗

class WithClass ():
    def __init__(self):
        self.value = "Bob"
    def my_func(self):
        print(self.value)

class WithoutClass ():
    value = "Bob"

    def my_func(self):
        print(self.value)
如果我使用或不使用
\uuuu init\uuu
方法来声明变量
,会有什么区别吗


我主要担心的是,我将以一种方式使用它,而这将给我带来更多的问题。

\uuuuuu init\uuuuu>之外设置的变量属于该类。它们被所有实例共享


\uuuu init\uuuu
(以及所有其他方法函数)中创建并以
self.
开头的变量属于对象实例

继S.Lott的回答之后,类变量被传递给元类new方法,并且在定义元类时可以通过字典访问。因此,即使在创建和实例化类之前,也可以访问类变量

例如:

class meta(type):
    def __new__(cls,name,bases,dicto):
          # two chars missing in original of next line ...
          if dicto['class_var'] == 'A':
             print 'There'
class proxyclass(object):
      class_var = 'A'
      __metaclass__ = meta
      ...
      ...

没有自我

创建一些对象:

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()
我可以更改c1实例,不会影响c2实例:

c1.x = 'changed instance'
c2.x
>>> 'original class'
但是如果我更改foo类,该类的所有实例也将更改:

foo.x = 'changed class'
c2.x
>>> 'changed class'
请注意Python作用域是如何工作的:

c1.x
>>> 'changed instance'
与自我

更改类不会影响实例:

class foo(object):
    def __init__(self):
        self.x = 'original self'

c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'

我想在我在这篇文章中读到的回复中添加一些东西(引用了这篇文章)

免责声明:这句话来自于我进行的实验

变量在
\uuuuu init\uuuu
之外:

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
事实上,这些是静态类变量,因此可以访问该类的所有实例

内部变量
\uuuu init\uuuu

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
这些实例变量的值仅可由手头的实例访问(通过
self
引用)

我的贡献

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
<> P>程序员在使用静态类变量时必须考虑的一件事是,它们可以被实例变量遮蔽(如果您通过“代码> >“自我/代码>引用”访问静态类变量)。

说明

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
在此之前,我认为声明变量的两种方式完全相同(愚蠢的我),这部分是因为我可以通过
self
引用访问这两种变量。现在,当我遇到麻烦时,我研究了这个话题并澄清了它

通过
self
reference是指如果没有同名的实例变量,它只引用静态类变量,更糟糕的是,尝试通过
self
引用重新定义静态类变量无效,因为创建了一个实例变量,该实例变量会隐藏以前可访问的静态类变量

为了解决这个问题,您应该始终通过类的名称引用静态类变量

示例

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
输出

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
我希望这对某人有帮助

class User(object):
    email = 'none'
    firstname = 'none'
    lastname = 'none'

    def __init__(self, email=None, firstname=None, lastname=None):
        self.email = email
        self.firstname = firstname
        self.lastname = lastname

    @classmethod
    def print_var(cls, obj):
        print ("obj.email obj.firstname obj.lastname")
        print(obj.email, obj.firstname, obj.lastname)
        print("cls.email cls.firstname cls.lastname")
        print(cls.email, cls.firstname, cls.lastname)

u1 = User(email='abc@xyz', firstname='first', lastname='last')
User.print_var(u1)
在上面的代码中,User类有3个全局变量,每个变量的值为“none”。u1是通过实例化此类创建的对象。print_var方法打印类用户的类变量值和对象u1的对象变量值。在下面显示的输出中,每个类变量
User.email
User.firstname
User.lastname
都有值
'none'
,而对象变量
u1.email
u1.firstname
u1.lastname
都有值
abc@xyz“
'first'
'last'

obj.email obj.firstname obj.lastname
('abc@xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')

如果跟踪类和实例字典,这很容易理解

class C:
   one = 42
   def __init__(self,val):
        self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)

结果如下:

{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
{'two':50}
{“模块”:“主模块”:“一”:42,“初始模块”:“指令模块”:“weakref”:“无”
注意:我在这里设置了完整的结果,但重要的是实例
ci
dict将只是
{'two':50}
,并且类字典中将包含
'one':42
键值对


这就是关于特定变量的所有知识。

类就像创建对象的蓝图。让我们用盖房子来比喻一下。你有房子的蓝图,这样你就可以盖房子了。你可以在你的资源允许的情况下建造尽可能多的房子

在这个比喻中,蓝图是类,房子是类的实例化,创建一个对象

这些房子有一些共同的属性,比如有屋顶、起居室等。这就是使用init方法的地方。它使用所需的属性构造对象(房屋)

假设您有:

`class house:`
`roof = True`
`def __init__(self, color):`
`self.wallcolor = color`
>创建小金锁的房子:

>> goldlock = house() #() invoke's class house, not function

>> goldlock.roof

>> True

all house's have roofs, now let's define goldlock's wall color to white:

>> goldlock.wallcolor = 'white'
>>goldlock.wallcolor
>> 'white'

在Python中,类附带了成员函数(方法)、类变量、属性/实例变量(可能还有类方法):


通过创建对象的实例

my_employee = Employee("John", "Wood", "Software Engineer")
我们本质上触发了
\uuuu init\uuuu
,它将初始化新创建的
员工的实例变量。这意味着
\u first\u name
\u last\u name
\u position
是特定
我的员工
实例的显式参数

同样,成员函数返回信息或更改特定实例的状态


现在,在构造函数
\uuuu init\uuuu
之外定义的任何变量都被视为类变量。这些变量在类的所有实例中共享

john = Employee("John", "Wood", "Software Engineer")
bob = Employee("Bob", "Smith", "DevOps Engineer0")

print(john.get_full_name())
print(bob.get_full_name())
print(john.company)
print(bob.company)

>>> John Wood
>>> Bob Smith
>>> mycompany.com
>>> mycompany.com
还可以使用类方法来更改类的所有实例的类变量。例如:

@classmethod
def change_my_companys_name(cls, name):
    cls.company = name
现在
更改我公司的名称()

将对类
员工的所有实例生效:

print(bob.company)
print(john.company)

>>> mynewcompany.com
>>> mynewcompany.com
考虑到foo根本无法访问x(F