首页 文章

静态类变量可能吗?

提问于
浏览
1598

是否可以在python中使用静态类变量或方法?这样做需要什么语法?

16 回答

  • 2

    静态和类方法

    正如其他答案所指出的那样,使用内置装饰器可以轻松完成静态和类方法:

    class Test(object):
    
        # regular instance method:
        def MyMethod(self):
            pass
    
        # class method:
        @classmethod
        def MyClassMethod(klass):
            pass
    
        # static method:
        @staticmethod
        def MyStaticMethod():
            pass
    

    像往常一样, MyMethod() 的第一个参数绑定到类实例对象 . 相反, MyClassMethod() 的第一个参数绑定到类对象本身(例如,在这种情况下, Test ) . 对于 MyStaticMethod() ,没有绑定任何参数,并且根本没有参数是可选的 .

    “静态变量”

    然而,实现"static variables"(好吧,可变的静态变量,无论如何,如果这不是一个矛盾......)并不是那么简单 . 作为millerdev pointed out in his answer,问题是Python的类属性不是真正的"static variables" . 考虑:

    class Test(object):
        i = 3  # This is a class attribute
    
    x = Test()
    x.i = 12   # Attempt to change the value of the class attribute using x instance
    assert x.i == Test.i  # ERROR
    assert Test.i == 3    # Test.i was not affected
    assert x.i == 12      # x.i is a different object than Test.i
    

    这是因为 x.i = 12 行已将新实例属性 i 添加到 x ,而不是更改 Testi 属性的值 .

    部分预期的静态变量行为,即多个实例之间的属性同步(但 not 与类本身;请参阅下面的"gotcha"),可以通过将class属性转换为属性来实现:

    class Test(object):
    
        _i = 3
    
        @property
        def i(self):
            return type(self)._i
    
        @i.setter
        def i(self,val):
            type(self)._i = val
    
    ## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
    ## (except with separate methods for getting and setting i) ##
    
    class Test(object):
    
        _i = 3
    
        def get_i(self):
            return type(self)._i
    
        def set_i(self,val):
            type(self)._i = val
    
        i = property(get_i, set_i)
    

    现在你可以这样做:

    x1 = Test()
    x2 = Test()
    x1.i = 50
    assert x2.i == x1.i  # no error
    assert x2.i == 50    # the property is synced
    

    现在,静态变量将在所有类实例之间保持同步 .

    (注意:也就是说,除非一个类实例决定定义自己的 _i 版本!但如果有人决定这样做,他们应该得到他们得到的,不是吗?)

    请注意,从技术上讲, i 仍然不是'static variable';它是一个 property ,它是一种特殊类型的描述符 . 但是, property 行为现在等效于在所有类实例中同步的(可变)静态变量 .

    不可变“静态变量”

    对于不可变的静态变量行为,只需省略 property setter:

    class Test(object):
    
        _i = 3
    
        @property
        def i(self):
            return type(self)._i
    
    ## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
    ## (except with separate methods for getting i) ##
    
    class Test(object):
    
        _i = 3
    
        def get_i(self):
            return type(self)._i
    
        i = property(get_i)
    

    现在尝试设置实例 i 属性将返回 AttributeError

    x = Test()
    assert x.i == 3  # success
    x.i = 12         # ERROR
    

    有一点需要意识到

    请注意,上述方法仅适用于您的类的实例 - 它们在使用类本身时将会起作用 . 例如:

    x = Test()
    assert x.i == Test.i  # ERROR
    
    # x.i and Test.i are two different objects:
    type(Test.i)  # class 'property'
    type(x.i)     # class 'int'
    

    assert Test.i == x.i 行产生错误,因为 Testxi 属性是两个不同的对象 .

    很多人会发现这令人惊讶 . 但是,它不应该 . 如果我们返回并检查我们的 Test 类定义(第二个版本),我们会注意到这一行:

    i = property(get_i)
    

    显然, Test 的成员 i 必须是 property 对象,它是从 property 函数返回的对象类型 .

    如果您发现上述令人困惑,您很可能仍会从其他语言(例如Java或c)的角度考虑它 . 您应该研究 property 对象,关于返回Python属性的顺序,描述符协议和方法解析顺序(MRO) .

    我提出了上述'gotcha'的解决方案;但是我会建议 - 极力 - 你不要尝试做类似下面的事情,直到 - 至少 - 你完全理解为什么 assert Test.i = x.i 会导致错误 .

    REAL,ACTUAL静态变量 - Test.i == x.i

    我在下面提供(Python 3)解决方案仅供参考 . 我并不赞同它是一个“好的解决方案” . 我怀疑是否真的需要在Python中模拟其他语言的静态变量行为 . 但是,无论它是否真的有用,下面的内容都应该有助于进一步了解Python的工作原理 .

    更新:这次尝试 is really pretty awful ;如果你坚持做这样的事情(暗示:请不要; Python是一种非常优雅的语言,而且它只是不需要表现得像另一种语言),请使用Ethan Furman's answer中的代码 .

    Emulating static variable behavior of other languages using a metaclass

    元类是类的类 . Python中所有类的默认元类(即我认为的Python 2.3之后的"new style"类)是 type . 例如:

    type(int)  # class 'type'
    type(str)  # class 'type'
    class Test(): pass
    type(Test) # class 'type'
    

    但是,您可以像这样定义自己的元类:

    class MyMeta(type): pass
    

    并将其应用到您自己的类中(仅限Python 3):

    class MyClass(metaclass = MyMeta):
        pass
    
    type(MyClass)  # class MyMeta
    

    下面是我创建的元类,它试图模仿其他语言的“静态变量”行为 . 它基本上可以通过用版本替换默认的getter,setter和deleter来工作,这些版本检查所请求的属性是否是“静态变量” .

    "static variables"的目录存储在 StaticVarMeta.statics 属性中 . 最初尝试使用替代分辨率顺序来解析所有属性请求 . 我把它称为"static resolution order",或"SRO" . 这是通过在给定类(或其父类)的"static variables"集中查找所请求的属性来完成的 . 如果该属性未出现在"SRO"中,则该类将回退到默认属性get / set / delete行为(即"MRO") .

    from functools import wraps
    
    class StaticVarsMeta(type):
        '''A metaclass for creating classes that emulate the "static variable" behavior
        of other languages. I do not advise actually using this for anything!!!
    
        Behavior is intended to be similar to classes that use __slots__. However, "normal"
        attributes and __statics___ can coexist (unlike with __slots__). 
    
        Example usage: 
    
            class MyBaseClass(metaclass = StaticVarsMeta):
                __statics__ = {'a','b','c'}
                i = 0  # regular attribute
                a = 1  # static var defined (optional)
    
            class MyParentClass(MyBaseClass):
                __statics__ = {'d','e','f'}
                j = 2              # regular attribute
                d, e, f = 3, 4, 5  # Static vars
                a, b, c = 6, 7, 8  # Static vars (inherited from MyBaseClass, defined/re-defined here)
    
            class MyChildClass(MyParentClass):
                __statics__ = {'a','b','c'}
                j = 2  # regular attribute (redefines j from MyParentClass)
                d, e, f = 9, 10, 11   # Static vars (inherited from MyParentClass, redefined here)
                a, b, c = 12, 13, 14  # Static vars (overriding previous definition in MyParentClass here)'''
        statics = {}
        def __new__(mcls, name, bases, namespace):
            # Get the class object
            cls = super().__new__(mcls, name, bases, namespace)
            # Establish the "statics resolution order"
            cls.__sro__ = tuple(c for c in cls.__mro__ if isinstance(c,mcls))
    
            # Replace class getter, setter, and deleter for instance attributes
            cls.__getattribute__ = StaticVarsMeta.__inst_getattribute__(cls, cls.__getattribute__)
            cls.__setattr__ = StaticVarsMeta.__inst_setattr__(cls, cls.__setattr__)
            cls.__delattr__ = StaticVarsMeta.__inst_delattr__(cls, cls.__delattr__)
            # Store the list of static variables for the class object
            # This list is permanent and cannot be changed, similar to __slots__
            try:
                mcls.statics[cls] = getattr(cls,'__statics__')
            except AttributeError:
                mcls.statics[cls] = namespace['__statics__'] = set() # No static vars provided
            # Check and make sure the statics var names are strings
            if any(not isinstance(static,str) for static in mcls.statics[cls]):
                typ = dict(zip((not isinstance(static,str) for static in mcls.statics[cls]), map(type,mcls.statics[cls])))[True].__name__
                raise TypeError('__statics__ items must be strings, not {0}'.format(typ))
            # Move any previously existing, not overridden statics to the static var parent class(es)
            if len(cls.__sro__) > 1:
                for attr,value in namespace.items():
                    if attr not in StaticVarsMeta.statics[cls] and attr != ['__statics__']:
                        for c in cls.__sro__[1:]:
                            if attr in StaticVarsMeta.statics[c]:
                                setattr(c,attr,value)
                                delattr(cls,attr)
            return cls
        def __inst_getattribute__(self, orig_getattribute):
            '''Replaces the class __getattribute__'''
            @wraps(orig_getattribute)
            def wrapper(self, attr):
                if StaticVarsMeta.is_static(type(self),attr):
                    return StaticVarsMeta.__getstatic__(type(self),attr)
                else:
                    return orig_getattribute(self, attr)
            return wrapper
        def __inst_setattr__(self, orig_setattribute):
            '''Replaces the class __setattr__'''
            @wraps(orig_setattribute)
            def wrapper(self, attr, value):
                if StaticVarsMeta.is_static(type(self),attr):
                    StaticVarsMeta.__setstatic__(type(self),attr, value)
                else:
                    orig_setattribute(self, attr, value)
            return wrapper
        def __inst_delattr__(self, orig_delattribute):
            '''Replaces the class __delattr__'''
            @wraps(orig_delattribute)
            def wrapper(self, attr):
                if StaticVarsMeta.is_static(type(self),attr):
                    StaticVarsMeta.__delstatic__(type(self),attr)
                else:
                    orig_delattribute(self, attr)
            return wrapper
        def __getstatic__(cls,attr):
            '''Static variable getter'''
            for c in cls.__sro__:
                if attr in StaticVarsMeta.statics[c]:
                    try:
                        return getattr(c,attr)
                    except AttributeError:
                        pass
            raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
        def __setstatic__(cls,attr,value):
            '''Static variable setter'''
            for c in cls.__sro__:
                if attr in StaticVarsMeta.statics[c]:
                    setattr(c,attr,value)
                    break
        def __delstatic__(cls,attr):
            '''Static variable deleter'''
            for c in cls.__sro__:
                if attr in StaticVarsMeta.statics[c]:
                    try:
                        delattr(c,attr)
                        break
                    except AttributeError:
                        pass
            raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
        def __delattr__(cls,attr):
            '''Prevent __sro__ attribute from deletion'''
            if attr == '__sro__':
                raise AttributeError('readonly attribute')
            super().__delattr__(attr)
        def is_static(cls,attr):
            '''Returns True if an attribute is a static variable of any class in the __sro__'''
            if any(attr in StaticVarsMeta.statics[c] for c in cls.__sro__):
                return True
            return False
    
  • 14

    您还可以动态地将类变量添加到类中

    >>> class X:
    ...     pass
    ... 
    >>> X.bar = 0
    >>> x = X()
    >>> x.bar
    0
    >>> x.foo
    Traceback (most recent call last):
      File "<interactive input>", line 1, in <module>
    AttributeError: X instance has no attribute 'foo'
    >>> X.foo = 1
    >>> x.foo
    1
    

    类实例可以更改类变量

    class X:
      l = []
      def __init__(self):
        self.l.append(1)
    
    print X().l
    print X().l
    
    >python test.py
    [1]
    [1, 1]
    
  • 24

    @Blair Conrad说在类定义中声明的静态变量,但不在方法内部是类或“静态”变量:

    >>> class Test(object):
    ...     i = 3
    ...
    >>> Test.i
    3
    

    这里有一些问题 . 继续上面的例子:

    >>> t = Test()
    >>> t.i     # static variable accessed via instance
    3
    >>> t.i = 5 # but if we assign to the instance ...
    >>> Test.i  # we have not changed the static variable
    3
    >>> t.i     # we have overwritten Test.i on t by creating a new attribute t.i
    5
    >>> Test.i = 6 # to change the static variable we do it by assigning to the class
    >>> t.i
    5
    >>> Test.i
    6
    >>> u = Test()
    >>> u.i
    6           # changes to t do not affect new instances of Test
    
    # Namespaces are one honking great idea -- let's do more of those!
    >>> Test.__dict__
    {'i': 6, ...}
    >>> t.__dict__
    {'i': 5}
    >>> u.__dict__
    {}
    

    注意直接在 t 上设置属性 i 时,实例变量 t.i 如何与"static"类变量不同步 . 这是因为 it 名称空间内重新绑定,这与 Test 名称空间不同 . 如果要更改"static"变量的值,则必须在最初定义它的范围(或对象)内更改它 . 我把"static"放在引号中,因为Python在C和Java的意义上并没有真正的静态变量 .

    虽然它没有说明有关静态变量或方法的任何内容,但Python tutorialclasses and class objects上有一些相关信息 .

    @Steve Johnson也回答了有关静态方法的问题,也在Python Library Reference的“内置函数”中进行了介绍 .

    class Test(object):
        @staticmethod
        def f(arg1, arg2, ...):
            ...
    

    @beid还提到了classmethod,类似于staticmethod . classmethod的第一个参数是类对象 . 例:

    class Test(object):
        i = 3 # class (or static) variable
        @classmethod
        def g(cls, arg):
            # here we can use 'cls' instead of the class name (Test)
            if arg > cls.i:
                cls.i = arg # would the the same as  Test.i = arg1
    
  • 3

    有可能有 static 类变量,但可能不值得努力 .

    这是用Python 3编写的概念验证 - 如果任何确切的细节都是错误的,可以调整代码以匹配 static variable 的任何意思:


    class Static:
        def __init__(self, value, doc=None):
            self.deleted = False
            self.value = value
            self.__doc__ = doc
        def __get__(self, inst, cls=None):
            if self.deleted:
                raise AttributeError('Attribute not set')
            return self.value
        def __set__(self, inst, value):
            self.deleted = False
            self.value = value
        def __delete__(self, inst):
            self.deleted = True
    
    class StaticType(type):
        def __delattr__(cls, name):
            obj = cls.__dict__.get(name)
            if isinstance(obj, Static):
                obj.__delete__(name)
            else:
                super(StaticType, cls).__delattr__(name)
        def __getattribute__(cls, *args):
            obj = super(StaticType, cls).__getattribute__(*args)
            if isinstance(obj, Static):
                obj = obj.__get__(cls, cls.__class__)
            return obj
        def __setattr__(cls, name, val):
            # check if object already exists
            obj = cls.__dict__.get(name)
            if isinstance(obj, Static):
                obj.__set__(name, val)
            else:
                super(StaticType, cls).__setattr__(name, val)
    

    并在使用中:

    class MyStatic(metaclass=StaticType):
        """
        Testing static vars
        """
        a = Static(9)
        b = Static(12)
        c = 3
    
    class YourStatic(MyStatic):
        d = Static('woo hoo')
        e = Static('doo wop')
    

    和一些测试:

    ms1 = MyStatic()
    ms2 = MyStatic()
    ms3 = MyStatic()
    assert ms1.a == ms2.a == ms3.a == MyStatic.a
    assert ms1.b == ms2.b == ms3.b == MyStatic.b
    assert ms1.c == ms2.c == ms3.c == MyStatic.c
    ms1.a = 77
    assert ms1.a == ms2.a == ms3.a == MyStatic.a
    ms2.b = 99
    assert ms1.b == ms2.b == ms3.b == MyStatic.b
    MyStatic.a = 101
    assert ms1.a == ms2.a == ms3.a == MyStatic.a
    MyStatic.b = 139
    assert ms1.b == ms2.b == ms3.b == MyStatic.b
    del MyStatic.b
    for inst in (ms1, ms2, ms3):
        try:
            getattr(inst, 'b')
        except AttributeError:
            pass
        else:
            print('AttributeError not raised on %r' % attr)
    ms1.c = 13
    ms2.c = 17
    ms3.c = 19
    assert ms1.c == 13
    assert ms2.c == 17
    assert ms3.c == 19
    MyStatic.c = 43
    assert ms1.c == 13
    assert ms2.c == 17
    assert ms3.c == 19
    
    ys1 = YourStatic()
    ys2 = YourStatic()
    ys3 = YourStatic()
    MyStatic.b = 'burgler'
    assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
    assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
    assert ys1.d == ys2.d == ys3.d == YourStatic.d
    assert ys1.e == ys2.e == ys3.e == YourStatic.e
    ys1.a = 'blah'
    assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
    ys2.b = 'kelp'
    assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
    ys1.d = 'fee'
    assert ys1.d == ys2.d == ys3.d == YourStatic.d
    ys2.e = 'fie'
    assert ys1.e == ys2.e == ys3.e == YourStatic.e
    MyStatic.a = 'aargh'
    assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
    
  • 1

    绝对是的,Python本身没有明确的静态数据成员,但我们可以这样做

    class A:
        counter =0
        def callme (self):
            A.counter +=1
        def getcount (self):
            return self.counter  
    >>> x=A()
    >>> y=A()
    >>> print(x.getcount())
    >>> print(y.getcount())
    >>> x.callme() 
    >>> print(x.getcount())
    >>> print(y.getcount())
    

    产量

    0
    0
    1
    1
    

    说明

    here object (x) alone increment the counter variable
    from 0 to 1 by not object y. But result it as "static counter"
    
  • 5

    您还可以使用元类强制使用静态类 .

    class StaticClassError(Exception):
        pass
    
    
    class StaticClass:
        __metaclass__ = abc.ABCMeta
    
        def __new__(cls, *args, **kw):
            raise StaticClassError("%s is a static class and cannot be initiated."
                                    % cls)
    
    class MyClass(StaticClass):
        a = 1
        b = 3
    
        @staticmethod
        def add(x, y):
            return x+y
    

    然后,每当你偶然尝试初始化 MyClass 时,你会得到一个StaticClassError .

  • 160

    我发现的最好方法是使用另一个类 . 您可以创建一个对象,然后在其他对象上使用它 .

    class staticFlag:
        def __init__(self):
            self.__success = False
        def isSuccess(self):
            return self.__success
        def succeed(self):
            self.__success = True
    
    class tryIt:
        def __init__(self, staticFlag):
            self.isSuccess = staticFlag.isSuccess
            self.succeed = staticFlag.succeed
    
    tryArr = []
    flag = staticFlag()
    for i in range(10):
        tryArr.append(tryIt(flag))
        if i == 5:
            tryArr[i].succeed()
        print tryArr[i].isSuccess()
    

    通过上面的例子,我创建了一个名为 staticFlag 的类 .

    该类应该呈现静态var __success (私有静态Var) .

    tryIt 类代表我们需要使用的常规类 .

    现在我为一个标志( staticFlag )创建了一个对象 . 此标志将作为对所有常规对象的引用发送 .

    所有这些对象都被添加到列表 tryArr 中 .


    此脚本结果:

    False
    False
    False
    False
    False
    True
    True
    True
    True
    True
    
  • 6

    我个人在需要静态方法时会使用classmethod . 主要是因为我把 class 作为一个论点 .

    class myObj(object):
       def myMethod(cls)
         ...
       myMethod = classmethod(myMethod)
    

    或使用装饰

    class myObj(object):
       @classmethod
       def myMethod(cls)
    

    对于静态属性..它查找一些python定义的时间..变量总是可以改变 . 它们有两种类型,它们是可变的和不可变的 . 此外,还有类属性和实例属性 . 在java和c的意义上,没有什么比静态属性更像

    为什么在pythonic意义上使用静态方法,如果它对类没有任何关系!如果我是你,我要么使用classmethod,要么定义独立于类的方法 .

  • 5

    为了避免任何潜在的混淆,我想对比静态变量和不可变对象 .

    一些原始对象类型,如整数,浮点数,字符串和操作,在Python中是不可变的 . 这意味着如果给定名称引用的对象是上述对象类型之一,则该对象不能更改 . 可以将名称重新分配给其他对象,但不能更改对象本身 .

    通过禁止变量名指向任何对象但它当前指向的对象,使变量静态更进一步 . (注意:这是一般软件概念,并非特定于Python;有关在Python中实现静态的信息,请参阅其他人的帖子) .

  • 8

    python中的静态方法称为classmethod s . 看看下面的代码

    class MyClass:
    
        def myInstanceMethod(self):
            print 'output from an instance method'
    
        @classmethod
        def myStaticMethod(cls):
            print 'output from a static method'
    
    >>> MyClass.myInstanceMethod()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unbound method myInstanceMethod() must be called [...]
    
    >>> MyClass.myStaticMethod()
    output from a static method
    

    请注意,当我们调用方法myInstanceMethod时,我们会收到错误 . 这是因为它要求在此类的实例上调用该方法 . 方法myStaticMethod使用decorator @classmethod设置为classmethod .

    只是为了踢和傻笑,我们可以通过传入类的实例来调用类上的myInstanceMethod,如下所示:

    >>> MyClass.myInstanceMethod(MyClass())
    output from an instance method
    
  • 13

    关于这个answer,对于常量静态变量,可以使用描述符 . 这是一个例子:

    class ConstantAttribute(object):
        '''You can initialize my value but not change it.'''
        def __init__(self, value):
            self.value = value
    
        def __get__(self, obj, type=None):
            return self.value
    
        def __set__(self, obj, val):
            pass
    
    
    class Demo(object):
        x = ConstantAttribute(10)
    
    
    class SubDemo(Demo):
        x = 10
    
    
    demo = Demo()
    subdemo = SubDemo()
    # should not change
    demo.x = 100
    # should change
    subdemo.x = 100
    print "small demo", demo.x
    print "small subdemo", subdemo.x
    print "big demo", Demo.x
    print "big subdemo", SubDemo.x
    

    导致 ...

    small demo 10
    small subdemo 100
    big demo 10
    big subdemo 10
    

    如果静静地忽略设置值(上面的 pass )不是你的事情,你总是可以引发异常 . 如果您正在寻找C,Java样式的静态类变量:

    class StaticAttribute(object):
        def __init__(self, value):
            self.value = value
    
        def __get__(self, obj, type=None):
            return self.value
    
        def __set__(self, obj, val):
            self.value = val
    

    有关描述符的更多信息,请查看this answer和官方文档HOWTO .

  • 3

    在类定义中声明但在方法内部未声明的变量是类或静态变量:

    >>> class MyClass:
    ...     i = 3
    ...
    >>> MyClass.i
    3
    

    正如@ millerdev指出的那样,这会创建一个类级 i 变量,但这与任何实例级 i 变量不同,所以你可以拥有

    >>> m = MyClass()
    >>> m.i = 4
    >>> MyClass.i, m.i
    >>> (3, 4)
    

    这与C和Java不同,但与C#没有什么不同,在C#中,使用对实例的引用无法访问静态成员 .

    what the Python tutorial has to say on the subject of classes and class objects .

    @Steve Johnson已经回答static methods,也记录在"Built-in Functions" in the Python Library Reference下 .

    class C:
        @staticmethod
        def f(arg1, arg2, ...): ...
    

    @beidy推荐classmethod s over staticmethod,因为该方法然后接收类类型作为第一个参数,但是我很重要 .

  • 3

    关于Python的属性查找的一个非常有趣的观点是它可以用于创建“virtual变量”:

    class A(object):
    
      label="Amazing"
    
      def __init__(self,d): 
          self.data=d
    
      def say(self): 
          print("%s %s!"%(self.label,self.data))
    
    class B(A):
      label="Bold"  # overrides A.label
    
    A(5).say()      # Amazing 5!
    B(3).say()      # Bold 3!
    

    通常在创建它们之后不会对它们进行任何赋值 . 请注意,查找使用 self ,因为尽管 label 在未与特定实例关联的意义上是静态的,但该值仍取决于(实例的类) .

  • 1575

    在任何成员方法之外定义某个成员变量时,该变量可以是静态变量,也可以是非静态变量,具体取决于变量的表达方式 .

    • CLASSNAME.var是静态变量

    • INSTANCENAME.var不是静态变量 .
      类中的

    • self.var不是静态变量 .
      未定义类成员函数内的

    • var .

    例如:

    #!/usr/bin/python
    
    class A:
        var=1
    
        def printvar(self):
            print "self.var is %d" % self.var
            print "A.var is %d" % A.var
    
    
        a = A()
        a.var = 2
        a.printvar()
    
        A.var = 3
        a.printvar()
    

    结果是

    self.var is 2
    A.var is 1
    self.var is 2
    A.var is 3
    
  • 542

    类工厂python3.6中的静态变量

    对于使用带有 python3.6 的类工厂的任何人,请使用 nonlocal 关键字将其添加到正在创建的类的范围/上下文中,如下所示:

    >>> def SomeFactory(some_var=None):
    ...     class SomeClass(object):
    ...         nonlocal some_var
    ...         def print():
    ...             print(some_var)
    ...     return SomeClass
    ... 
    >>> SomeFactory(some_var="hello world").print()
    hello world
    
  • 13

    有关静态属性和实例属性的一个特别注意事项,如下例所示:

    class my_cls:
      my_prop = 0
    
    #static property
    print my_cls.my_prop  #--> 0
    
    #assign value to static property
    my_cls.my_prop = 1 
    print my_cls.my_prop  #--> 1
    
    #access static property thru' instance
    my_inst = my_cls()
    print my_inst.my_prop #--> 1
    
    #instance property is different from static property 
    #after being assigned a value
    my_inst.my_prop = 2
    print my_cls.my_prop  #--> 1
    print my_inst.my_prop #--> 2
    

    这意味着在将值赋给instance属性之前,如果我们尝试通过'instance访问属性,则使用静态值 . Each property declared in python class always has a static slot in memory .

相关问题