python - 전역변수 - 파이썬 클래스 메소드



정적 클래스 변수가 가능합니까? (11)

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

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


Answer #1

정적 및 클래스 메서드

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

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

"정적 변수"

그러나 "정적 변수"(잘 모르는 정적 변수, 어쨌든, 그것이 모순이 아니라면 ...)를 구현하는 것은 그리 간단하지 않습니다. Millerdev 가 그의 답변에서 지적했듯이 , 문제는 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

이는 xi = 12 행이 Test 클래스 i 속성의 값을 변경하는 대신 x 새 인스턴스 속성 i 를 추가했기 때문입니다.

부분적으로 예상되는 정적 변수 동작, 즉 여러 인스턴스간에 속성 동기화 (즉, 클래스 자체가 아니라 아래 "잡기"참조)는 클래스 속성을 속성으로 변환하여 수행 할 수 있습니다.

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

하나의 Gotcha에 대한 인식

위의 메소드는 클래스의 인스턴스 에서만 작동 합니다 . 클래스 자체를 사용할 때는 작동 하지 않습니다 . 그래서 예를 들면 :

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'

Testii 속성이 두 개의 서로 다른 객체이므로 assert Test.i == xi 는 오류를 생성합니다.

많은 사람들이이 사실을 알게 될 것입니다. 그러나, 그렇게해서는 안됩니다. 돌아가서 Test 클래스 정의 (두 번째 버전)를 검사하면 다음 줄을 기록합니다.

    i = property(get_i) 

분명히, Test i 멤버는 property 함수에서 반환 된 객체의 유형 인 property 객체 여야합니다.

위의 내용이 혼란 스러우면 다른 언어 (예 : Java 또는 c ++)의 관점에서 생각할 가능성이 큽니다. property 객체, Python 속성이 반환되는 순서, 설명자 프로토콜 및 MRO (method resolution order)에 대해 공부해야합니다.

아래의 위의 '잡았다'에 대한 해결책을 제시합니다. 그러나 나는 적어도 - assert Test.i = xiassert Test.i = xi 인해 오류가 발생하는 이유를 철저히 이해할 때까지 다음과 같은 것을 시도하지 말 것을 assert Test.i = xi 합니다.

실제, 실제 정적 변수 - Test.i == xi

나는 아래의 (Python 3) 솔루션만을 정보 제공의 목적으로 제시한다. 나는 "좋은 해결책"으로 그것을지지하지 않습니다. 파이썬에서 다른 언어의 정적 변수 동작을 에뮬레이션하는지 여부에 대해서는 필자가 의심의 여지가있다. 그러나 실제로 유용한 지 여부에 관계없이 아래에서 Python이 어떻게 작동하는지 더 자세히 이해할 수 있습니다.

업데이트 :이 시도 는 정말 끔찍합니다 . 만약 당신이 이와 같은 일을 주장한다면 (힌트 : 제발하지 마세요. 파이썬은 매우 우아한 언어이고, 다른 언어처럼 행동하는 것을 구두로 삼을 필요는 없습니다), Ethan Furman의 답변에 코드를 대신 사용하십시오.

메타 클래스를 사용하여 다른 언어의 정적 변수 동작을 에뮬레이트합니다.

메타 클래스는 클래스의 클래스입니다. 파이썬에서 모든 클래스의 기본 메타 클래스 (즉, "새로운 스타일"클래스 인 Python 2.3이 내가 믿는다)는 type 이다. 예 :

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

그러나 다음과 같이 자신 만의 메타 클래스를 정의 할 수 있습니다.

class MyMeta(type): pass

그리고 이것을 자신 만의 클래스에 적용하십시오 (파이썬 3에만 해당) :

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

아래는 다른 언어의 "정적 변수"동작을 모방하려는 메타 클래스입니다. 기본적으로 기본 getter, setter 및 deleter를 요청되는 속성이 "정적 변수"인지 확인하는 버전으로 대체하여 작동합니다.

"정적 변수"의 카탈로그는 StaticVarMeta.statics 속성에 저장됩니다. 모든 속성 요청은 우선 대체 해결 순서를 사용하여 해석되도록 시도됩니다. 저는 이것을 "고정 해상도 순서"또는 "SRO"라고 불렀습니다. 이는 주어진 클래스 (또는 그 부모 클래스)에 대한 "정적 변수"집합에서 요청 된 속성을 찾는 것입니다. 속성이 "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

Answer #2

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

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

또는 데코레이터 사용

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

정적 속성 .. 그 시간에 당신은 파이썬 정의를 찾는다 .. 변수는 항상 바뀔 수있다. 거기에는 두 가지 유형이 있습니다. 변경 가능하고 변경할 수 없습니다. 또한 클래스 속성과 인스턴스 속성이 있습니다. Java 및 C ++의 의미에서 정적 속성을 사용하는 것은 아무 것도 없습니다.

왜 클래스에 관계가없는 경우 정적 메서드를 파이썬 적 의미로 사용하십시오! 내가 너라면, 클래스 메서드를 사용하거나 클래스와 독립적 인 메서드를 정의 할 것이다.


Answer #3

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

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

Answer #4

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

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


Answer #5

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

  • 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

Answer #6

이 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

디스크립터에 대한 더 자세한 정보는 이 대답 과 공식 docs HOWTOHOWTO .


Answer #7

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

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

변수를 정적으로 만들려면 변수 이름이 현재 가리키는 객체가 아닌 객체를 가리키는 것을 허용하지 않아야합니다. (참고 : 이것은 일반적인 소프트웨어 개념이며 Python과 관련이 없으며 다른 사람들의 게시물을 참조하여 Python에서 정적을 구현하는 방법에 대한 정보를 참조하십시오).


Answer #8

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

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

@ millerdev 지적했듯이, 이것은 클래스 수준의 i 변수를 생성하지만 이것은 어떤 인스턴스 수준의 변수와도 구분되므로

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

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

Python 튜토리얼이 클래스와 클래스 객체의 주제에 관해 무엇을 말해야하는지 보십시오.

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

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

@beidy는 staticmethod에 대해 classmethod 권장합니다. 메서드가 첫 번째 인수로 클래스 유형을 수신하기 때문에 staticmethod에 비해이 접근법의 장점에 대해 약간 퍼지기 쉽습니다. 너도 그렇다면 아마 문제가되지 않을 것이다.


Answer #9

파이썬의 애트리뷰트 룩업에 대한 매우 흥미로운 점 중 하나는 " 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!

일반적으로 생성 된 후에는 할당이 없습니다. label특정 인스턴스와 연관되지 않는다는 의미에서 정적이지만 값은 여전히 ​​(인스턴스의) 클래스에 따라 달라지기 때문에 조회는 self 사용합니다.


Answer #10

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




class-variables