类__init __()函数内部和外部的变量

时间:2009-10-08 11:25:28

标签: python class

我试图理解,除了名字之外,这些类之间是否有任何区别?如果我在声明变量“value”时使用或不使用__init __()函数会有什么不同吗?

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)

我主要担心的是,我会以一种方式使用它,因为这会导致我的问题进一步发展(目前我使用的是init调用)。

10 个答案:

答案 0 :(得分:197)

__init__之外的变量集属于该类。它们由所有实例共享。

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

答案 1 :(得分:69)

没有自我

创建一些对象:

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'

答案 2 :(得分:5)

在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
      ...
      ...

答案 3 :(得分:1)

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打印类User的类变量的值和对象u1的对象变量。在下面显示的输出中,每个类变量User.emailUser.firstnameUser.lastname都具有值'none',而对象变量u1.emailu1.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')

答案 4 :(得分:0)

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

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}

请注意,我在此处设置了完整结果,但重要的是实例ci字典将仅为{'two': 50},并且类字典中将包含'one': 42键值对。 / p>

这是您应该了解的特定变量的全部信息。

答案 5 :(得分:0)

类就像创建对象的蓝图。让我们用盖房子来做个比喻。您已经有了房屋的蓝图,因此可以建造房屋。您可以在资源允许的范围内建造尽可能多的房屋。

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

房屋具有共同的属性,例如具有屋顶,起居室等。初始化方法就是在这里进行的。它使用所需的属性构造对象(房屋)。

让我们假设您拥有:

`class house:`
`roof = True`
`def __init__(self, collor):`
`self.wallcolor = collor`

>> create little goldlock's house:

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

>> goldlock.roof

>> True

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

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

答案 6 :(得分:0)

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

class Employee:

    # Class Variable
    company = "mycompany.com"

    def __init__(self, first_name, last_name, position):
        # Instance Variables
        self._first_name = first_name
        self._last_name = last_name
        self._position = position

    # Member function
    def get_full_name(self):
        return f"{self._first_name} {self._last_name}"

通过创建对象的实例

my_employee = Employee("John", "Wood", "Software Engineer")

我们实际上触发了__init__,该初始化初始值是新创建的Employee instance变量。这意味着_first_name_last_name_position是特定 my_employee实例的显式参数。

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


现在,在构造函数__init__外部定义的任何变量都被视为类变量。这些变量在该类的所有实例之间共享。

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

您还可以使用 class方法来更改类的所有实例的类变量。例如:

@classmethod
def change_my_companys_name(cls, name):
    cls.company = name

现在是change_my_companys_name()

bob.change_my_companys_name("mynewcompany.com")

将对类Employee的所有实例生效:

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

>>> mynewcompany.com
>>> mynewcompany.com

答案 7 :(得分:0)

class foo(object):
    mStatic = 12

    def __init__(self):
        self.x = "OBj"

考虑foo根本无法访问x(FACT)

现在的冲突在于通过实例或直接通过类访问mStatic。

从Python的内存管理方面考虑:

内存中有12个值,名称为mStatic(可从类中访问)

指向它。

c1, c2 = foo(), foo() 

此行产生两个实例,其中包括名称mStatic指向值12(到现在)。

foo.mStatic = 99 

这将使mStatic名称指向内存中具有新值99的新位置。

并且由于(婴儿)c1,c2仍在(爸爸)foo之后,因此它们具有相同的名称(c1.mStatic和c2.mStatic),指向相同的新值。

但是一旦每个婴儿决定独自行走,情况就会有所不同:

c1.mStatic ="c1 Control"
c2.mStatic ="c2 Control"

从现在以后,该家族(c1,c2,foo)中的每个人的mStatica都指向不同的值。

[请尝试在我们讨论过的不同状态下对所有(c1,c2,foo)使用id()函数,我认为这会使情况变得更好]

这就是我们现实生活的方式。儿子从父亲那里继承了一些信念,这些信念仍然与父亲的信念相同,直到儿子决定改变它。

希望会帮助

答案 8 :(得分:0)

示例代码:

class inside:
    def __init__(self):
        self.l = []

    def insert(self, element):
        self.l.append(element)


class outside:
    l = []             # static variable - the same for all instances

    def insert(self, element):
        self.l.append(element)


def main():
    x = inside()
    x.insert(8)
    print(x.l)      # [8]
    y = inside()
    print(y.l)      # []
    # ----------------------------
    x = outside()
    x.insert(8)
    print(x.l)      # [8]
    y = outside()
    print(y.l)      # [8]           # here is the difference


if __name__ == '__main__':
    main()

答案 9 :(得分:0)

正如 S.Lott 所指出的,

<块引用>

init 之外的变量集属于类。他们分享了 所有实例。

init(以及所有其他方法函数)中创建的变量和 以自我开头。属于对象实例。

但是, 请注意,类变量可以通过 self. 直到它们被具有相似名称的对象变量屏蔽 这意味着在为其赋值之前读取 self. 将返回该值Class. 但之后它将返回 obj. 。这是一个例子

In [20]: class MyClass: 
    ...:     elem = 123 
    ...:  
    ...:     def update(self,i): 
    ...:         self.elem=i  
    ...:     def print(self): 
    ...:         print (MyClass.elem, self.elem) 
    ...:  
    ...: c1 = MyClass()  
    ...: c2 = MyClass() 
    ...: c1.print() 
    ...: c2.print()                                                                                                                                                                                                                                                               
123 123 
123 123 
In [21]: c1.update(1) 
    ...: c2.update(42) 
    ...: c1.print() 
    ...: c2.print()                                                                                                                                                                                                                                                               
123 1 
123 42
In [22]: MyClass.elem=22 
    ...: c1.print()  
    ...: c2.print()                                                                                                                                                                                                                                                               
22 1 
22 42

第二点:考虑slots。它们可能提供一种更好的方法来实现对象变量。