문제

파이썬에서 정적 클래스 변수나 메소드를 가질 수 있습니까?이를 수행하려면 어떤 구문이 필요합니까?

도움이 되었습니까?

해결책

클래스 정의 내부에 선언되었지만 메서드 내부에는 선언되지 않은 변수는 클래스 또는 정적 변수입니다.

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

처럼 @밀러데브 지적하면 이는 클래스 수준의 i 변수이지만 이는 인스턴스 수준과는 다릅니다. i 변수가 있으므로

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

이는 C++ 및 Java와 다르지만 인스턴스에 대한 참조를 사용하여 정적 멤버에 액세스할 수 없는 C#과 크게 다르지 않습니다.

보다 클래스 및 클래스 객체 주제에 관해 Python 튜토리얼에서 말하는 내용.

@Steve Johnson은 이미 이에 대해 답변했습니다. 정적 메소드, 아래에도 문서화되어 있습니다. Python 라이브러리 참조의 "내장 함수".

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

@beidy가 추천합니다 수업 방법메소드는 클래스 유형을 첫 번째 인수로 수신하므로 정적 메소드보다 s이지만 정적 메소드에 비해 이 접근 방식의 장점에 대해서는 여전히 약간 모호합니다.당신도 그렇다면 아마도 중요하지 않을 것입니다.

다른 팁

@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 속성이 "정적" 클래스 변수와 동기화되지 않았습니다. i 직접 설정했습니다 t.이 때문입니다 i 내에 다시 바인딩되었습니다. t 네임스페이스와 구별되는 Test 네임스페이스."정적" 변수의 값을 변경하려면 해당 변수가 원래 정의된 범위(또는 개체) 내에서 변경해야 합니다.Python에는 실제로 C++ 및 Java와 같은 정적 변수가 없기 때문에 "정적"을 따옴표로 묶었습니다.

정적 변수나 메소드에 대해 구체적으로 언급하지는 않지만 파이썬 튜토리얼 관련 정보가 있습니다 클래스와 클래스 객체.

@Steve Johnson은 또한 Python 라이브러리 참조의 "내장 함수" 아래에 문서화되어 있는 정적 메서드에 관해 답변했습니다.

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

@beid는 또한 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

정적 및 클래스 메서드

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

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(), 인수 중 어느 것도 바인딩되지 않으며 인수를 갖는 것은 선택 사항입니다.

"정적 변수"

그러나 "정적 변수"를 구현하는 것은(음, 변하기 쉬운 어쨌든 정적 변수는 용어상 모순이 아니라면...) 그렇게 간단하지 않습니다.밀러데브로서 그의 대답에서 지적했다, 문제는 Python의 클래스 속성이 진정한 "정적 변수"가 아니라는 것입니다.고려하다:

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 값을 변경하는 대신 Test 수업 i 기인하다.

부분 예상되는 정적 변수 동작, 즉 여러 인스턴스 간의 속성 동기화(그러나 ~ 아니다 수업 자체와 함께;아래의 "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

알아야 할 한 가지 문제

위의 방법은 다음에서만 작동합니다. 인스턴스 당신 수업의 - 그들은 것입니다 ~ 아니다 일하다 클래스 자체를 사용할 때.예를 들면 다음과 같습니다.

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 오류가 발생합니다. 왜냐하면 i 속성 Test 그리고 x 두 개의 서로 다른 개체입니다.

많은 사람들이 이것이 놀랍다고 생각할 것입니다.그러나 그래서는 안됩니다.우리가 돌아가서 검사한다면 Test 클래스 정의(두 번째 버전)에서는 다음 줄에 주목합니다.

    i = property(get_i) 

분명히 그 회원은 i ~의 Test 이어야 합니다 property object는 반환된 개체의 유형입니다. property 기능.

위의 내용이 혼란스럽다면 여전히 다른 언어의 관점에서 생각하고 있을 가능성이 높습니다(예:자바 또는 C++).너는 가서 공부해야 해. property Python 속성이 반환되는 순서, 설명자 프로토콜 및 MRO(메서드 확인 순서)에 대한 개체입니다.

나는 위의 '문제'에 대한 해결책을 아래에 제시합니다.그러나 나는 최소한 이유를 완전히 이해할 때까지 다음과 같은 작업을 시도하지 말 것을 강력히 제안합니다. assert Test.i = x.i 오류가 발생합니다.

실제, 실제 정적 변수 - 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.__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

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

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

개인적으로 나는 정적 메서드가 필요할 때마다 클래스 메서드를 사용했습니다.주로 수업을 논쟁으로 받아들이기 때문입니다.

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

또는 데코레이터를 사용하십시오

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

정적 속성의 경우..이제 파이썬 정의를 찾아볼 시간입니다..변수는 항상 바뀔 수 있습니다.변경 가능(mutable)과 불변(immutable) 두 가지 유형이 있습니다.그리고 클래스 속성과 인스턴스 속성이 있습니다.Java 및 C++의 의미에서 정적 속성을 정말 좋아하는 것은 없습니다.

클래스와 아무런 관련이 없다면 왜 파이썬적인 의미에서 정적 메소드를 사용합니까?내가 당신이라면 classmethod를 사용하거나 클래스와 독립적으로 메서드를 정의할 것입니다.

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

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

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

Python의 정적 메소드가 호출됩니다. 수업 방법에스.다음 코드를 살펴보세요.

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

메소드를 호출할 때 주의하세요. myInstance메소드, 오류가 발생합니다.이는 이 클래스의 인스턴스에서 메서드를 호출해야 하기 때문입니다.방법 myStatic메소드 다음을 사용하여 클래스 메서드로 설정됩니다. 장식가 @classmethod.

단지 신나게 웃고 낄낄대기 위해, 우리는 전화할 수 있었어 myInstance메소드 다음과 같이 클래스의 인스턴스를 전달하여 클래스에 대해:

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

멤버 메서드 외부에서 일부 멤버 변수를 정의하는 경우 변수가 표현되는 방식에 따라 변수는 정적이거나 비정적일 수 있습니다.

  • 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

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

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

그런 다음 실수로 초기화를 시도할 때마다 내 수업 StaticClassError가 발생합니다.

가질 수 있다 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

Python의 속성 조회에 대한 매우 흥미로운 점 중 하나는 "가상 변수":

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 와 연관되지 않는다는 의미에서 정적입니다. 특정한 인스턴스의 경우 값은 여전히 ​​인스턴스(클래스)에 따라 달라집니다.

이에 관해서 답변, 끊임없는 정적 변수인 경우 설명자를 사용할 수 있습니다.예는 다음과 같습니다.

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

보세요 이 답변 그리고 공식 문서 어떻게 설명자에 대한 자세한 내용은

절대적으로, 파이썬 자체는 정적 데이터 구성원이 명시 적으로 없지만 그렇게함으로써 가질 수 있습니다.

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"

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

정수, 부동 소수점, 문자열 및 튜플과 같은 일부 기본 객체 유형은 Python에서 변경할 수 없습니다.이는 주어진 이름으로 참조되는 개체가 앞서 언급한 개체 유형 중 하나인 경우 변경할 수 없음을 의미합니다.이름은 다른 개체에 다시 할당할 수 있지만 개체 자체는 변경할 수 없습니다.

변수를 정적으로 만들면 변수 이름이 현재 가리키는 개체 이외의 개체를 가리키는 것을 허용하지 않음으로써 한 단계 더 발전합니다.(메모:이것은 일반적인 소프트웨어 개념이며 Python에만 국한된 것이 아닙니다.Python에서 정적 구현에 대한 정보는 다른 사람의 게시물을 참조하세요.)

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

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.

이 클래스는 정적 변수를 제공해야 합니다. __success (개인 정적 변수).

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

이제 하나의 플래그에 대한 객체를 만들었습니다(staticFlag).이 플래그는 모든 일반 개체에 대한 참조로 전송됩니다.

이 모든 개체가 목록에 추가되고 있습니다. tryArr.


이 스크립트 결과:

False
False
False
False
False
True
True
True
True
True

예, Python에서 정적 변수와 메서드를 작성하는 것은 확실히 가능합니다.

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

    >>> 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 클래스를 사용하여 직접 액세스할 수 있습니다.인스턴스를 생성할 필요가 없습니다.

그러나 Python에서는 정적 메서드가 비정적 메서드를 호출할 수 없다는 점을 명심하세요.

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

클래스 팩토리 python3.6의 정적 변수

클래스 팩토리를 사용하는 모든 사람의 경우 파이썬3.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

변수 또는 객체 유형이 포함 된 클래스를 만듭니다.아래와 같은 클래스 이름을 사용하여 해당 변수에 액세스하십시오.


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


    StaticVariable.myvar1 = StaticVariable.myvar1 +1
    StaticVariable.myvar2 = StaticVariable.myvar2 +1

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top