web-dev-qa-db-ja.com

静的クラス変数は可能ですか?

Pythonで静的クラス変数やメソッドを持つことは可能ですか?これを行うにはどのような構文が必要ですか?

1695
Andrew Walker

@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__
{}

属性itに直接設定されていると、インスタンス変数t.iが「静的」クラス変数と同期しなくなったことに注意してください。これは、itネームスペースとは別のものであるTestネームスペース内で再バインドされたためです。 「静的」変数の値を変更したい場合は、それが最初に定義されていたスコープ(またはオブジェクト)内で変更する必要があります。 PythonはC++やJavaのように静的変数を実際には持っていないので、引用符で "static"を入れます。

静的な変数やメソッドについて具体的なことは何も述べていませんが、 Pythonチュートリアル には クラスとクラスオブジェクトに関するいくつかの関連情報があります

@Steve Johnsonは静的メソッドに関しても回答しました。これもPython Library Referenceの "Built-in Functions"に記載されています。

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

@beidはclassmethodにも言及しました。これはstaticmethodに似ています。クラスメソッドの最初の引数はクラスオブジェクトです。例:

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()の場合、引数はどれもバインドされず、引数を持つことはオプションです。

「静的変数」

しかし、 "静的変数"(よく、 変更可能 静的変数など)を実装することは、それが矛盾していなければ...それほど単純ではありません。 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

これは、iクラスのx属性の値を変更するのではなく、行x.i = 12が新しいインスタンス属性Testiに追加したためです。

部分的 期待される静的変数の振る舞い、すなわち複数のインスタンス間での属性の同期(ただし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

気をつけるべき一つのガッチャ

上記のメソッドはあなたのクラスの インスタンス でのみ動作することに注意してください - それらはwork - ではありません クラス自体を使用しているとき です。

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'

iTest属性とxは2つの異なるオブジェクトであるため、行assert Test.i == x.iはエラーを生成します。

多くの人がこれを驚くべきことに気づくでしょう。しかし、そうではありません。戻ってTestクラス定義(2番目のバージョン)を調べると、この行に注意してください。

    i = property(get_i) 

明らかに、iのメンバTestpropertyオブジェクトでなければなりません。これはproperty関数から返されるオブジェクトの型です。

上記のことがわかりにくい場合は、他の言語(Javaやc ++など)の観点から検討している可能性があります。 Pythonの属性が返される順番、記述子プロトコル、そしてメソッド解決の順番(MRO)について、propertyオブジェクトを調べてください。

私は上記の 'gotcha'に対する解決策を以下に提示します。しかし、私は - 精力的に - あなたがassert Test.i = x.iがエラーを引き起こす理由を - 徹底的に理解するまで - あなたが以下のようなことをしようとしないことを提案するでしょう。

REAL、ACTUAL 静的変数 - Test.i == x.i

私は情報提供のみを目的として以下の(Python 3)ソリューションを提示します。私はそれを「良い解決策」として承認していません。私は、Pythonで他の言語の静的変数の振る舞いをエミュレートすることが実際に必要かどうかについて疑問を抱いています。しかし、それが実際に有用であるかどうかにかかわらず、以下はPythonがどのように機能するのかをさらに理解するのに役立ちます。

UPDATE:この試みは本当にひどいものです;このようなことをやろうとするなら(ヒント:しないでください。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」に表示されない場合、クラスはデフォルトの属性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.__+ " 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
165
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)

静的プロパティの場合..その時はPythonの定義を調べます。変数はいつでも変更できます。変更可能と不変の2つのタイプがあります。また、クラス属性とインスタンス属性があります。

クラスに関係なく、Pythonicの意味で静的メソッドを使用するのはなぜでしょう。私があなただったら、classmethodを使うか、クラスから独立したメソッドを定義します。

15
emb

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 は、 デコレータ @classmethod を使用してクラスメソッドとして設定されます。

キックと笑いのためだけに、次のようにクラスのインスタンスを渡すことでクラスで myInstanceMethod を呼び出すことができます。

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

以下の例に示すように、静的プロパティとインスタンスプロパティについて注意すべき特別なことが1つあります。

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クラスで宣言された各プロパティは常にメモリ内に静的スロットを持っています

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

Pythonの属性検索に関する非常に興味深い点は、それが " virtual variables"を作成するために使用できるということです。

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

もちろん、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"
4
Mari Selvan

この answer に関して、 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という名前のクラスを作りました。

このクラスはstatic var __success(Private Static Var)を提示するべきです。

tryItクラスは、使用する必要がある通常のクラスを表します。

今、私は1つのフラグ(staticFlag)のオブジェクトを作りました。このフラグは、すべての通常のオブジェクトへの参照として送信されます。

これらすべてのオブジェクトは、リストtryArrに追加されています。


このスクリプトの結果

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

混乱を避けるために、静的変数と不変オブジェクトを対比させたいと思います。

整数、浮動小数点数、文字列、タプルなどの基本的なオブジェクト型は、Pythonでは不変です。つまり、特定の名前で参照されるオブジェクトは、それが前述のオブジェクトタイプのいずれかであれば変更できません。名前を別のオブジェクトに割り当て直すことはできますが、オブジェクト自体を変更することはできません。

変数を静的にすると、変数名が現在指しているオブジェクト以外のオブジェクトを指し示すことができなくなり、このステップがさらに一歩進みます。 (注:これは一般的なソフトウェアの概念であり、Pythonに固有のものではありません。Pythonに統計を実装する方法については、他の投稿を参照してください).

3
Ross

はい。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!!
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