it-swarm-tr.com

Statik sınıf değişkenleri mümkün mü?

Python'da statik sınıf değişkenler veya yöntemler olabilir mi? Bunu yapmak için hangi sözdizimi gereklidir?

1695
Andrew Walker

Sınıf tanımında bildirilen, ancak bir yöntemin içinde olmayan değişkenler sınıf veya statik değişkenlerdir:

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

@ millerdev işaret ettiği gibi, bu bir sınıf düzeyinde ideğişkeni yaratır, ancak bu herhangi bir örnek düzeyinde ideğişkeninden farklıdır;

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

Bu, C++ ve Java'dan farklıdır, ancak statik bir üyeye bir örneğe referans kullanılarak erişilemediğinde C # 'dan çok farklı değildir.

Bkz. Python öğreticisinin sınıflar ve sınıf nesneleri hakkında söylediklerini.

@ Steve Johnson, statik yöntemler ile ilgili olarak zaten cevap verdi "Dahili İşlevler" altında Python Kütüphane Referansı .

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

@beidy, statik metot üzerinde classmethod s yöntemini önerir, çünkü yöntem daha sonra birinci argüman olarak sınıf türünü alır, ancak bu yaklaşımın avantajlarından dolayı hala biraz bulanıkım durukyöntem. Sen de öyleyse, o zaman önemli değil.

1738
Blair Conrad

@Blair Conrad, sınıf tanımının içinde bildirilen statik değişkenlerin, bir yöntemin içinde olmayan sınıf veya "statik" değişkenler olduğunu söyledi:

>>> class Test(object):
...     i = 3
...
>>> Test.i
3

Burada birkaç tane var. Yukarıdaki örnekten devam etmek:

>>> 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 örnek değişkeninin, i niteliği doğrudan t öğesine ayarlandığında "statik" sınıf değişkeni ile nasıl eşitlendiğine dikkat edin. Bunun nedeni i'ın t ad alanından farklı olan Test ad alanı içinde yeniden bağlanmış olmasıdır. Bir "statik" değişkenin değerini değiştirmek istiyorsanız, onu başlangıçta tanımlandığı kapsamda (veya nesnede) değiştirmelisiniz. Python'un C++ ve Java gibi anlamında statik değişkenleri olmadığından, "statik" ifadesini tırnak içine aldım.

Statik değişkenler veya yöntemler hakkında özel bir şey söylemese de, Python tutorial , class ve class nesneleri hakkında bazı önemli bilgiler içerir.

@ Steve Johnson ayrıca Python Kütüphanesi Referansında "Dahili İşlevler" altında belgelenen statik yöntemlerle ilgili olarak cevap verdi.

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

@beid ayrıca, statik metaloda benzer olan sınıf metodu da belirtmiştir. Bir sınıf yönteminin ilk argümanı, sınıf nesnesidir. Örnek:

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

Statik ve Sınıf Yöntemleri

Diğer cevapların da belirttiği gibi, statik ve sınıf yöntemleri yerleşik dekoratörler kullanılarak kolayca gerçekleştirilir:

class Test(object):

    # regular instance method:
    def MyMethod(self):
        pass

    # class method:
    @classmethod
    def MyClassMethod(klass):
        pass

    # static method:
    @staticmethod
    def MyStaticMethod():
        pass

Her zamanki gibi, MyMethod() için ilk argüman sınıf örneği nesnesine bağlanır. Buna karşılık, MyClassMethod() için ilk argüman sınıf nesnesinin kendisine bağlı (örn. Bu durumda, Test) 'dir. MyStaticMethod() için, hiçbir argüman bağlı değildir ve hiçbir argümana sahip olmak isteğe bağlıdır.

"Statik Değişkenler"

Bununla birlikte, "statik değişkenler" (iyi, değiştirilebilir statik değişkenler uygulamak, yine de, eğer bu şekilde bir çelişki değilse ...) o kadar kolay değildir. Millerdev cevabına dikkat çekti olduğu gibi, sorun Python'un sınıf özelliklerinin gerçekten "statik değişkenler" olmamasıdır. Düşünmek:

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

Bunun nedeni, x.i = 12 satırının, i sınıf x niteliğinin değerini değiştirmek yerine Test öğesine i öğesine yeni bir örnek niteliği eklemesidir.

Kısmi beklenen statik değişken davranışı, yani, özniteliğin birden çok örnek arasında eşitlenmesi (ancak değil sınıfın kendisi ile; aşağıdaki "gotcha" bölümüne bakın), sınıf özniteliğini bir sınıf haline getirerek elde edilebilir. özellik, mal mülk, emlak:

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)

Şimdi yapabilirsin:

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced

Statik değişken şimdi senkronize kalacaktır tüm sınıf örnekleri arasında.

(NOT: Bu, bir sınıf örneği _i dosyasının kendi sürümünü tanımlamaya karar vermediği sürecedir. Ama eğer birileri BU'yu yapmaya karar verirse, ne elde ettiklerini hak eder, değil mi ???)

Teknik olarak konuşursak, i'ın hala bir 'statik değişken' olmadığını unutmayın; özel bir tanımlayıcı türü olan property. Ancak, property davranışı şimdi tüm sınıf örneklerinde senkronize edilen (değiştirilebilir) bir statik değişkene eşdeğerdir.

Değişmez "Statik Değişkenler"

Değişmez statik değişken davranış için 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)

Şimdi i niteliğini ayarlamaya çalışmak bir AttributeError döndürecektir:

x = Test()
assert x.i == 3  # success
x.i = 12         # ERROR

Bir Gotcha Farkında Olmalı

Yukarıdaki yöntemlerin yalnızca sınıfınızın örnekler ile çalıştığını unutmayın - bunlar çalışmazlar çalışma sınıfın kendisini kullanırken. Yani örneğin:

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 satırı, i ve Test öğelerinin x niteliği iki farklı nesne olduğundan, bir hata üretir.

Birçok insan bunu şaşırtıcı bulacaktır. Ancak, olmamalı. Geri dönüp Test sınıf tanımımızı (ikinci sürüm) incelersek, şu satırı not alırız:

    i = property(get_i) 

Açıkçası, i öğesinin Test üyesi, property işlevinden döndürülen nesne türü olan bir property nesnesi olmalıdır.

Yukarıdakileri kafa karıştırıcı bulursanız, muhtemelen hala diğer dillerin perspektifinden düşünebilirsiniz (örneğin, Java veya c ++). property nesnesini, Python özniteliklerinin döndürüldüğü sıra, tanımlayıcı protokol ve yöntem çözümleme sırasını (MRO) araştırmaya gitmelisiniz.

Aşağıdaki 'gotcha' için bir çözüm sunuyorum; ancak şunu önerebilirim - yorucu bir şekilde - aşağıdakilere benzer bir şey yapmaya çalışmadığınıza - en azından - neden assert Test.i = x.i öğesinin bir hataya neden olduğunu iyice anlayın.

REAL, ACTUAL Statik Değişkenler - Test.i == x.i

Aşağıdaki (Python 3) çözümünü yalnızca bilgi amaçlı sunuyorum. Bunu "iyi bir çözüm" olarak onaylamıyorum. Diğer dillerin statik değişken davranışını Python içinde taklit edip etmediğine dair şüphelerim gerçekten gerekli. Bununla birlikte, gerçekten yararlı olup olmadığına bakılmaksızın, aşağıdakiler Python'ın nasıl çalıştığını daha iyi anlamaya yardımcı olmalıdır.

GÜNCELLEME: Bu girişim gerçekten oldukça korkunç ; böyle bir şey yapmakta ısrar ediyorsanız (ipucu: lütfen yapmayın; Python çok zarif bir dildir ve başka bir dil gibi davranmak için ayakkabıyı kıpırdatmak gerekmez, sadece kodu kullanın - Ethan Furman'ın cevabı bunun yerine.

Bir metaclass kullanarak diğer dillerin statik değişken davranışını taklit etme

Bir metaclass bir sınıfın sınıfıdır. Python (yani, "yeni stil" sınıfları Python (2 inanıyorum) yazılan tüm sınıflar için varsayılan metaclass type. Örneğin:

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

Bununla birlikte, kendi metaclass'ınızı şöyle tanımlayabilirsiniz:

class MyMeta(type): pass

Ve bunu kendi sınıfınıza uygulayın (yalnızca Python 3):

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

Aşağıda, diğer dillerin "statik değişken" davranışını taklit etmeye çalışan bir metaclass var. Temelde, varsayılan alıcı, ayarlayıcı ve silgiyi, istenen özniteliğin "statik bir değişken" olup olmadığını denetleyen sürümlerle değiştirerek çalışır.

"Statik değişkenler" in bir katalogu StaticVarMeta.statics niteliğinde saklanır. Tüm özellik istekleri başlangıçta bir yedek çözüm siparişi kullanılarak çözümlenmeye çalışılır. Bunu "statik çözünürlük emri" veya "SRO" olarak adlandırdım. Bu, belirli bir sınıf (veya ana sınıfları) için "statik değişkenler" setinde istenen niteliği arayarak yapılır. Eğer öznitelik "SRO" de görünmezse, sınıf, get/set/delete davranışındaki varsayılan özniteliğe geri döner (ör. "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

Sınıf değişkenlerini anında sınıflara da ekleyebilirsiniz.

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

Ve sınıf örnekleri sınıf değişkenlerini değiştirebilir

class X:
  l = []
  def __init__(self):
    self.l.append(1)

print X().l
print X().l

>python test.py
[1]
[1, 1]
24
Gregory

Şahsen statik bir yönteme ihtiyacım olduğunda bir sınıf metodu kullanırdım. Genelde sınıfı bir argüman olarak aldığım için.

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

veya bir dekoratör kullanın

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

Statik özellikler için .. Bir miktar python tanımı ararken zamanı .. değişken her zaman değişebilir. Bunların iki türü değişebilir ve değişmezdir. Ayrıca, sınıf nitelikleri ve örnek nitelikleri vardır. Java ve c ++ anlamında statik nitelikler gibisi yoktur.

Sınıfla ne alakası yoksa, neden statik metodu Pythonic anlamında kullanıyorsunuz? Yerinde olsam, ya sınıf metodu kullanırdım ya da sınıftan bağımsız metodu tanımlardım.

15
emb

Python'daki statik yöntemlere classmethod s adı verilir. Aşağıdaki koda bir göz atın

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 metodunu çağırdığımızda bir hata aldığımızı fark edin. Bunun nedeni, bu yöntemin bu sınıfın bir örneğinde çağrılmasını gerektirmesidir. myStaticMethod yöntemi, decorator @classmethod kullanılarak bir sınıf metodu olarak ayarlanır.

Sadece tekmeler ve kıkırdamalar için, sınıfın bir örneğinden geçerek sınıftaki myInstanceMethod 'yi çağırabiliriz, şöyle:

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

Aşağıdaki örnekte gösterilen statik özellikler ve örnek özellikler hakkında not edilmesi gereken özel bir şey:

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

Bu, değeri example özelliğine atamadan önce, 'thru' özelliğine erişmeye çalışırsak, statik değer kullanılır. python sınıfında bildirilen her özellik daima bellekte statik bir alana sahiptir .

13
jondinham

Herhangi bir üye yönteminin dışında bir üye değişkeni tanımlarken değişken, değişimin nasıl ifade edildiğine bağlı olarak statik veya statik olmayabilir.

  • CLASSNAME.var statik değişkendir
  • INSTANCENAME.var statik değişken değil.
  • sınıf içindeki self.var statik değişken değildir.
  • sınıf üyesi işlevi içindeki var tanımlanmadı.

Örneğin:

#!/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()

Sonuçları

self.var is 2
A.var is 1
self.var is 2
A.var is 3
8
user2209576

static sınıf değişkenlerine sahip olmak mümkündür, ancak muhtemelen çabaya değmez.

İşte Python 3'te yazılmış bir kavram kanıtı - eğer ayrıntılardan herhangi birinin yanlış olması durumunda, kod bir static variable ile ne demek istediğinizi tam olarak eşleştirmek için düzenlenebilir:


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)

ve kullanımda:

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

ve bazı testler:

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

Ayrıca bir sınıfı metaclass kullanarak statik olması için zorlayabilirsiniz.

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

O zaman kazayla ne zaman başlatmaya çalışırsanız MyClass bir StaticClassError alacaksınız.

6

Python'un özellik aramasıyla ilgili çok ilginç bir nokta, " virtual değişkenleri" oluşturmak için kullanılabileceğidir:

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!

Normalde bunlar oluşturulduktan sonra bunlara herhangi bir atama yoktur. Aramanın self işlevini kullandığına dikkat edin, çünkü label bir özel örneği ile ilişkilendirilmemesi açısından statik olmasına rağmen, değer yine de (sınıfının) örneğine bağlıdır.

5
Davis Herring

Kesinlikle Evet, Python kendi başına açık bir şekilde statik veri üyesine sahip değil, ancak bunu yapabiliriz.

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

çıktı

0
0
1
1

açıklama

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

Bununla ilgili olarak answer , a constant static değişkeni için bir tanımlayıcı kullanabilirsiniz. İşte bir örnek:

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

sonuçlanan ...

small demo 10
small subdemo 100
big demo 10
big subdemo 10

Ayar değerini sessizce göz ardı etmek (yukarıdaki pass) her zaman bir istisna oluşturabilirsiniz. C++ arıyorsanız, Java tarzı statik sınıf değişkeni:

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

Tanımlayıcılar hakkında daha fazla bilgi için bu yanıt ve resmi belgelere HOWTO göz atın.

4
Yann

Bulduğum en iyi yol, başka bir sınıf kullanmak. Bir nesne oluşturabilir ve sonra diğer nesnelerde kullanabilirsiniz.

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

Yukarıdaki örnekte staticFlag adında bir sınıf yaptım.

Bu sınıf statik var __success (Özel Statik Var) göstermelidir.

tryIt sınıfı, kullanmamız gereken normal sınıfı temsil ediyordu.

Şimdi bir bayrak için bir nesne yaptım (staticFlag). Bu bayrak tüm normal nesnelere referans olarak gönderilecektir.

Tüm bu nesneler tryArr listesine ekleniyor.


Bu Script Sonuçları:

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

Herhangi bir olası karışıklığı önlemek için, statik değişkenleri ve değişmez nesneleri karşılaştırmak istiyorum.

Tam sayılar, kayan noktalar, dizeler ve perdeleri gibi bazı ilkel nesne türleri Python'da değişmezdir. Bu, belirli bir adla belirtilen nesnenin yukarıda belirtilen nesne türlerinden biri olması durumunda değiştirilemeyeceği anlamına gelir. Ad, farklı bir nesneye atanabilir, ancak nesnenin kendisi değişmeyebilir.

Bir değişkeni statik yapmak, bir adımı, şu anda işaret ettiği nesneyi işaret etmek için değişken ismine izin vermeyerek daha da ileri götürür. (Not: Bu genel bir yazılım konseptidir ve Python'a özgü değildir; lütfen Python'da statiği uygulama hakkında bilgi almak için başkalarının yayınlarına bakınız).

3
Ross

Evet, python'da statik değişkenler ve yöntemler yazmak kesinlikle mümkün.

Statik Değişkenler: Sınıf düzeyinde bildirilen Değişken, doğrudan sınıf adı kullanılarak erişilebilen statik değişken olarak adlandırılır.

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

    >>> print(A.my_var)
        shagun

Örnek değişkenleri: Bir sınıf örneğiyle ilişkilendirilen ve erişilen değişkenler örnek değişkenleridir.

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

Statik Yöntemler: Değişkenlere benzer şekilde, statik yöntemlere doğrudan Sınıf Adı kullanılarak da erişilebilir. Örnek oluşturmanıza gerek yok.

Ancak aklınızda bulundurun, statik bir yöntem python'da statik olmayan bir yöntem diyemez.

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

Sınıf fabrikalarındaki Statik Değişkenler python3.6

python3.6 ve üstü bir sınıf fabrikası kullanan herkes, bu şekilde oluşturulan sınıfın kapsamına/bağlamına eklemek için nonlocal anahtar sözcüğünü kullanın:

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