it-gundan.com

정적 클래스 변수가 가능하면?

정적 클래스 변수 또는 메서드를 파이썬으로 가질 수 있습니까? 이를 수행하기 위해 필요한 구문은 무엇입니까?

1695
Andrew Walker

@ 브래어 콘래드는 클래스 정의 안에 선언 된 정적 변수는 있지만 클래스 또는 "정적"변수는 메소드 안에 없다고 말했습니다.

>>> 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가 속성 it에 직접 설정되었을 때 "정적"클래스 변수와 어떻게 동기화되지 않았는지 확인하십시오. 이것은 i 네임 스페이스와는 다른 t 네임 스페이스 내에서 Test이 다시 바인딩 되었기 때문입니다. "정적"변수의 값을 변경하려면 원래 정의한 범위 (또는 객체) 내에서 변수를 변경해야합니다. 나는 파이썬이 C++과 자바가하는 의미에서 정적 변수를 가지지 않기 때문에 "정적"을 따옴표로 묶었습니다.

정적 변수 나 메소드에 대한 구체적인 내용은 없지만 Python tutorial 에는 클래스 및 클래스 객체 에 대한 관련 정보가 있습니다.

@Steve Johnson은 정적 메서드에 관해서도 대답했으며, Python Library Reference의 "Built-in Functions"에도 설명되어 있습니다.

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

@bid는 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

Pictorial Representation Of Above Example

558
millerdev

정적 및 클래스 메소드

다른 답변에서 언급했듯이 정적 및 클래스 메서드는 내장 데코레이터를 사용하여 쉽게 수행 할 수 있습니다.

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()의 경우 인수가 바인드되지 않으며 인수를 갖는 것이 선택 사항입니다.

"정적 변수"

그러나 "정적 변수"(물론 mutable 정적 변수를 구현하는 것은 어쨌든 용어로 모순되지 않는 경우 ...)를 구현하는 것은 간단하지 않습니다. millerdev 자신의 대답에서 지적 된 로, 문제는 파이썬의 클래스 속성이 실제로 "정적 변수"가 아니라는 것입니다. 중히 여기다:

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에 추가했기 때문입니다.

Partial 예상되는 정적 변수 동작, 즉 여러 인스턴스 간의 속성 동기화 (그러나 not ​​클래스 자체와의 동기화, 아래 "gotcha"참조) 클래스 속성을 속성으로 바꿔서 달성하십시오.

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은 여전히 ​​'정적 변수'가 아닙니다. 특수한 유형의 설명자인 property입니다. 그러나 property 동작은 이제 모든 클래스 인스턴스에서 동기화 된 (변경 가능) 정적 변수와 동일합니다.

불변의 "정적 변수"

불변 정적 변수 동작의 경우, 간단히 property 설정자를 생략하십시오.

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

인식해야 할 하나의 문제

위의 메소드는 클래스의 instances 에서만 작동합니다. not ​​작동 클래스 자체를 사용할 때 . 예를 들어 :

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'

iTestx 속성이 서로 다른 두 개체이므로 assert Test.i == x.i 행에서 오류가 발생합니다.

많은 사람들이이 놀라운 것을 발견 할 것입니다. 그러나 그렇게해서는 안됩니다. 돌아가서 Test 클래스 정의 (두 번째 버전)를 검사하면 다음 행을 기록합니다.

    i = property(get_i) 

분명히 iTest 멤버는 property 함수에서 리턴 된 오브젝트 유형 인 property 오브젝트 여야합니다.

위의 내용이 혼동 될 경우 다른 언어 (예 : Java 또는 c ++)의 관점에서 여전히 생각하고 있습니다. Python 속성이 리턴되는 순서, 설명자 프로토콜 및 메소드 분석 순서 (MRO)에 대해 property 오브젝트를 연구해야합니다.

아래의 위의 'gotcha'에 대한 해결책을 제시합니다. 그러나 나는 assert Test.i = x.i가 왜 오류를 일으키는 지 철저히 이해할 때까지 다음과 같은 것을 시도하지 말 것을 강력하게 제안합니다.

REAL, ACTUAL 정적 변수-Test.i == x.i

정보 제공 목적으로 만 (Python 3) 솔루션을 제시합니다. 나는 그것을 "좋은 해결책"으로 보증하지 않습니다. Python에서 다른 언어의 정적 변수 동작을 에뮬레이션하는 것이 실제로 필요한지에 대한 의문이 있습니다. 그러나 실제로 유용한 지 여부에 관계없이 아래는 Python 작동 방식에 대한 추가 이해에 도움이됩니다.

업데이트 :이 시도 정말 끔찍합니다; 이 같은 일을 주장하는 경우 (힌트 : 제발하지 마십시오. Python은 매우 우아한 언어이며 다른 언어처럼 작동하도록 구두를 두르는 것은 불필요합니다)-코드를 사용하십시오- Ethan Furman의 답변 대신.

메타 클래스를 사용하여 다른 언어의 정적 변수 동작 모방

메타 클래스는 클래스의 클래스입니다. Python의 모든 클래스에 대한 기본 메타 클래스 (즉, Python 2.3의 "새 스타일"클래스 게시)는 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를 요청되는 속성이 "정적 변수"인지 확인하는 버전으로 대체하여 작동합니다.

"정적 변수"의 카탈로그는 StaticVarMeta.statics 속성에 저장됩니다. 모든 속성 요청은 초기에 대체 해결 순서를 사용하여 해결하려고 시도합니다. 나는 이것을 "정적 해상도 순서"또는 "SRO"라고 불렀다. 주어진 클래스 (또는 그 상위 클래스)에 대한 "정적 변수"세트에서 요청 된 속성을 찾아서 수행됩니다. 속성이 "SRO"에 나타나지 않으면 클래스는 기본 속성 가져 오기/설정/삭제 동작 (예 : "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.__+ " 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.__+ " 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
175
Rick Teachey

클래스에 클래스 변수를 즉시 추가 할 수도 있습니다.

>>> 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
Gregory

개인적으로 정적 메서드가 필요할 때마다 클래스 메서드를 사용합니다. 주로 클래스를 인수로 사용하기 때문입니다.

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

또는 데코레이터 사용

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

정적 속성 .. 그 시간은 당신이 파이썬 정의를 찾습니다. 변수는 항상 바뀔 수 있습니다. mutable과 immutable의 두 가지 유형이 있습니다. 또한 클래스 속성과 인스턴스 속성이 있습니다. Java & c ++의 의미에서 정적 속성을 정말로 좋아하는 것은 없습니다.

Pythonic 감각으로 정적 메서드를 사용하는 이유는 클래스에 관계가 없기 때문입니다. 내가 너라면, 클래스 메서드를 사용하거나 클래스와 독립적 인 메서드를 정의 할 것이다.

15
emb

파이썬의 정적 메소드는 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 를 사용하여 클래스 메소드로 설정됩니다.

걷어 차고 낄낄 거리기 만하면 다음과 같이 클래스의 인스턴스를 전달하여 클래스의 myInstanceMethod 를 호출 할 수 있습니다.

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

아래 예제와 같이 정적 속성 및 인스턴스 속성에 대해주의 할 특별한 사항은 다음과 같습니다.

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

즉, 값을 인스턴스 속성에 할당하기 전에 인스턴스에 대한 속성에 액세스하려고하면 정적 값이 사용됩니다. 파이썬 클래스에서 선언 된 각 속성은 항상 메모리에 정적 슬롯이 있습니다 .

13
jondinham

멤버 메서드 외부에서 일부 멤버 변수를 정의 할 때 변수는 변수가 표현되는 방식에 따라 정적 또는 비 정적 일 수 있습니다.

  • 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
8
user2209576

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
6
Ethan Furman

메타 클래스를 사용하여 클래스를 정적으로 유지할 수도 있습니다.

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가 발생합니다.

6
Bartosz Ptaszynski

파이썬의 속성 검색에 대한 매우 흥미로운 점 중 하나는 " 가상 변수"를 만드는 데 사용할 수 있다는 것입니다.

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을 사용합니다.

5
Davis Herring

절대적으로 그렇습니다. 파이썬 자체는 정적 데이터 멤버를 명시 적으로 가지고 있지 않지만 우리는 그렇게 할 수 있습니다.

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"
4
Mari Selvan

answer 와 관련하여 a constant static 변수의 경우 설명자를 사용할 수 있습니다. 다음은 그 예입니다.

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

설명자에 대한 자세한 내용은 이 답변 및 공식 문서 HOWTO 를보십시오.

4
Yann

내가 찾은 가장 좋은 방법은 다른 클래스를 사용하는 것입니다. 개체를 만든 다음 다른 개체에 사용할 수 있습니다.

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 (Private Static Var)를 제공해야합니다.

tryIt 클래스는 우리가 사용해야하는 정규 클래스를 나타냅니다.

이제 한 플래그 (staticFlag)에 대한 객체를 만들었습니다. 이 플래그는 모든 일반 오브젝트에 대한 참조로 보내집니다.

이러한 모든 개체가 tryArr 목록에 추가됩니다.


이 스크립트 결과 :

False
False
False
False
False
True
True
True
True
True
3
Tomer Zait

잠재적 인 혼동을 피하기 위해 정적 변수와 변경 불가능한 객체를 대조하고 싶습니다.

정수, 부동 소수점, 문자열 및 touples와 같은 일부 원시 객체 유형은 Python에서 불변입니다. 즉, 주어진 이름으로 참조되는 객체는 앞서 언급 한 객체 유형 중 하나 인 경우 변경할 수 없습니다. 이름은 다른 오브젝트로 재 지정할 수 있지만 오브젝트 자체는 변경 될 수 없습니다.

변수를 정적으로 만들려면 변수 이름이 현재 가리키는 오브젝트가 아닌 오브젝트를 가리 키지 못하도록하여이 단계를 더 진행하십시오. (참고 : 이것은 일반적인 소프트웨어 개념이며 파이썬에만 국한된 것은 아니며, 다른 사람들의 글을 참고하여 파이썬에서 정적을 구현하는 방법을 참조하십시오.).

3
Ross

그렇습니다. 파이썬에서 정적 변수와 메소드를 작성할 수 있습니다.

정적 변수 : 클래스 수준에서 선언 된 변수는 클래스 이름을 사용하여 직접 액세스 할 수있는 정적 변수라고합니다.

    >>> class A:
        ...my_var = "shagun"

    >>> print(A.my_var)
        shagun

인스턴스 변수 : 클래스의 인스턴스에 의해 액세스되고 액세스되는 변수는 인스턴스 변수입니다.

   >>> a = A()
   >>> a.my_var = "pruthi"
   >>> print(A.my_var,a.my_var)
       shagun pruthi

정적 메서드 : 변수와 유사하게 정적 메서드는 Name 클래스를 사용하여 직접 액세스 할 수 있습니다. 인스턴스를 만들 필요가 없습니다.

그러나, 정적 메소드는 파이썬에서 비 정적 메소드를 호출 할 수 없다는 것을 명심하십시오.

    >>> class A:
   ...     @staticmethod
   ...     def my_static_method():
   ...             print("Yippey!!")
   ... 
   >>> A.my_static_method()
   Yippey!!
2
Shagun Pruthi

클래스 팩토리의 정적 변수 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
1
jmunsch