質問

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

役に立ちましたか?

解決

クラス定義内で宣言されているがメソッド内では宣言されていない変数は、クラス変数または静的変数です。

>>> 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 がおすすめします クラスメソッドメソッドは最初の引数としてクラス型を受け取るため、静的メソッドよりも優れていますが、静的メソッドと比較したこのアプローチの利点についてはまだ少し曖昧です。あなたもそうであれば、それはおそらく問題ではありません。

他のヒント

@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 のような静的変数が実際には存在しないためです。

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

@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 新しいインスタンス属性が追加されました ix の値を変更する代わりに、 Test クラス 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 セッター:

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

注意すべき点が 1 つあります

上記のメソッドは次の場合にのみ機能することに注意してください。 インスタンス あなたのクラスの - 彼らはそうするでしょう ない 仕事 クラス自体を使用する場合. 。たとえば、次のようになります。

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 は 2 つの異なるオブジェクトです。

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

    i = property(get_i) 

明らかにメンバーは iTest でなければなりません property オブジェクト。 から返されるオブジェクトのタイプです。 property 関数。

上記の内容が混乱していると感じた場合は、おそらくまだ他の言語の観点から考えている可能性があります (例:Java または C++)。勉強しに行ったほうがいいよ property オブジェクト、Python 属性が返される順序、記述子プロトコル、およびメソッド解決順序 (MRO) について説明します。

上記の「落とし穴」に対する解決策を以下に示します。ただし、少なくともその理由を完全に理解するまでは、次のようなことを実行しないことを強くお勧めします。 assert Test.i = x.i エラーが発生します。

本物、実際 静的変数 - Test.i == x.i

情報提供のみを目的として、(Python 3) ソリューションを以下に示します。私はそれを「良い解決策」として支持しているわけではありません。他の言語の静的変数の動作を Python でエミュレートすることが実際に必要なのかどうかについては、私は疑問を持っています。ただし、実際に役立つかどうかに関係なく、以下の内容は Python がどのように機能するかをさらに理解するのに役立ちます。

アップデート:この試み 本当にかなりひどいです;このようなことをやりたい場合は (ヒント:やめてください。Python は非常にエレガントな言語であり、別の言語のように動作させるために無理に細工する必要はありません)。次のコードを使用します。 イーサン・ファーマンの答え その代わり。

メタクラスを使用して他の言語の静的変数の動作をエミュレートする

メタクラスはクラスのクラスです。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

以下は、他の言語の「静的変数」の動作をエミュレートしようとして作成したメタクラスです。これは基本的に、デフォルトのゲッター、セッター、およびデリーターを、要求されている属性が「静的変数」であるかどうかを確認するバージョンに置き換えることによって機能します。

「静的変数」のカタログは、 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)

静的プロパティの場合..Python の定義を調べてみましょう。変数は常に変化する可能性があります。それらには、可変と不変の 2 つのタイプがあります。また、クラス属性とインスタンス属性もあります。Java や C++ の意味での静的属性に似たものはありません

クラスと何の関係もないのに、Python 的な意味で静的メソッドを使用する必要はありません。私だったら、クラスメソッドを使用するか、クラスから独立してメソッドを定義するでしょう。

以下の例に示すように、静的プロパティとインスタンス プロパティに関して注意すべき特別な点が 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 クラスで宣言された各プロパティは常にメモリ内に静的スロットを持ちます。.

Pythonの静的メソッドは呼び出されます クラスメソッド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 を使用してクラスメソッドとして設定されます デコレーター @クラスメソッド.

キックとクスクス笑いのために、電話してもいいでしょう myInstanceMethod 次のように、クラスのインスタンスを渡すことによってクラス上で実行します。

>>> 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 の属性ルックアップに関する非常に興味深い点の 1 つは、それを使用して "バーチャル 変数":

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

見て この答え そして公式ドキュメント 方法 記述子の詳細については、

絶対にはい、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"

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

整数、浮動小数点、文字列、タプルなどの一部のプリミティブ オブジェクト型は、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 class は、使用する必要がある通常のクラスを表します。

今度は 1 つの旗のオブジェクトを作成しました (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

静的メソッド: 変数と同様に、静的メソッドにはクラス名を使用して直接アクセスできます。インスタンスを作成する必要はありません。

ただし、Python では静的メソッドは非静的メソッドを呼び出すことができないことに注意してください。

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

クラスファクトリーの静的変数 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

どんな変数やオブジェクトタイプを含むクラスを作成するだけです。以下のようにクラス名を使用してその変数にアクセスします。


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top