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


Python'da statik sınıf değişkenleri veya yöntemleri olması mümkün mü? Bunu yapmak için hangi sözdizimi gerekli?


1505
2017-09-16 01:46


Menşei




Cevaplar:


Sınıf tanımı içinde beyan edilen 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 

Gibi @millerdev Dikkat, bu bir sınıf seviyesi oluşturur i değişken, ancak bu herhangi bir düzey seviyesinden farklıdır i değişken, böylece sahip olabilirsiniz

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

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

Görmek Python öğreticisinin sınıflar ve sınıf nesneleri konusunda neler söylemesi gerektiği.

@Steve Johnson zaten ilgili yanıtladı statik yöntemler, ayrıca altında belgelenmiştir Python Kütüphane Referansında "Yerleşik İşlevler".

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

@beidy önerir classmethodBu yöntem, yöntemin ilk argümanı olarak sınıf tipini aldığı için, staticmethod üzerinde, ancak bu yaklaşımın staticmethod üzerindeki avantajları üzerinde hala biraz bulanıkım. Eğer sen de öyleyse, muhtemelen önemli değil.


1479
2017-09-16 01:51



Ben sadece Python'u öğreniyorum, ama avantajları @classmethod üzerinde @staticmethod AFAIK, bir alt sınıf olsa bile, yöntemin uygulandığı sınıfa her zaman sahip olmanızdır. Statik bir yöntem bu bilgiden yoksundur, bu nedenle örneğin geçersiz kılınmış bir yöntemi çağıramaz. - Seb
@TheJollySin sabitler için pythonik yol sabitler için bir sınıf büyümek değil. Sadece biraz var const.py ile PI = 3.14 ve her yerde alabilirsiniz. from const import PI - Giszmo
Bu cevabın statik değişken sorununu karıştırması olasıdır. Başlamak için i = 3 olduğu değil bir statik değişken, bir sınıf özniteliğidir ve bir örnek düzey özniteliğinden farklı olduğu için i o yapar değil Diğer dillerde bir statik değişken gibi davran. Görmek millerdev'nin cevabı, Yann'ın cevabı, ve cevabım altında. - Rick Teachey
yani sadece bir kopyası iBu sınıfın yüzlerce örneğini oluştursam bile (statik değişken) bellekte olacak? - sdream
Daniel'in @Dubslow yorumunda bahsettiği herkesin ilgisini çekmek için millerdev (yönlendirme makinesi) - HeyJude


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

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

Burada birkaç kaç 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__
{}

Örnek değişkenin nasıl olduğuna dikkat edin t.i özellik olduğunda "statik" sınıf değişkeniyle senkronizasyondan çıktı i doğrudan kuruldu t. Bunun nedeni ise i içinde yeniden bağlıydı t ad alanı, Test ad. Bir "statik" değişkenin değerini değiştirmek isterseniz, orijinal olarak tanımlandığı kapsam (veya nesne) içinde değiştirmeniz gerekir. Python'un C ++ ve Java'nın yaptığı anlamında gerçekten statik değişkenlere sahip olmadığı için tırnaklara "statik" koyuyorum.

Statik değişkenler veya yöntemler hakkında spesifik bir şey söylemese de, Python öğreticisi ilgili bazı bilgiler var sınıflar ve sınıf nesneleri.

@Steve Johnson ayrıca, Python Kütüphane Referansındaki "Yerleşik İşlevler" altında da belgelenen statik yöntemler hakkında da cevap verdi.

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

@beid ayrıca staticmethod'a benzeyen classmethod'dan da bahsetti. Bir classmethod'un 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


525
2017-09-16 03:04



Örneği biraz genişletmenizi öneririm: eğer Test.i = 6'yı ayarladıktan sonra, yeni bir nesneyi (örneğin, u = Test ()) başlatırsanız, yeni nesne yeni sınıf değerini "devralır" (örn. uI == 6) - Mark
Statik değişkenleri senkronize halde tutmanın bir yolu, bunları özellik olarak yapmaktır: class Test(object):, _i = 3, @property, def i(self),return type(self)._i, @i.setter, def i(self,val):, type(self)._i = val. Şimdi yapabilirsin x = Test(), x.i = 12, assert x.i == Test.i. - Rick Teachey
Bu yüzden tüm değişkenlerin başlangıçta statik olduğunu ve örneklere erişmenin örnek değişkenleri çalışma zamanında yapıldığını söyleyebilirim. - Ali
Belki de bu ilginçtir: Test.i'yi değiştiren Test'te bir yöntem tanımlarsanız, bu BOTH Test.i ve t.i değerlerini etkileyecektir. - Pablo


Statik ve Sınıf Yöntemleri

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

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, ilk argüman MyMethod() sınıf örneği nesnesine bağlanır. Aksine, ilk argüman MyClassMethod() olduğu sınıf nesnesinin kendisine bağlı (örneğin, bu durumda, Test). İçin MyStaticMethod()argümanların hiçbiri bağlayıcı değildir ve argümanların olması isteğe bağlıdır.

"Statik Değişkenler"

Ancak, "statik değişkenler" uygulamak (iyi, değişken Statik değişkenler, neyse, eğer bu bir çelişki değilse ...) düz ileri değil. Millerdev olarak cevabında dikkat çektiSorun, Python'un sınıf özniteliklerinin 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

Çünkü çizgi x.i = 12 yeni örnek özniteliği ekledi i için x değerini değiştirmek yerine Test sınıf i bağlıyor.

Kısmi beklenen statik değişken davranış, yani, birden çok örnek arasındaki özniteliğin senkronizasyonu (ancak değil sınıfın kendisi ile; Aşağıda "gotcha" bölümüne bakın, sınıf özelliğini bir özelliğe dönüştürerek elde edilebilir:

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 senkronizasyonda kalacak tüm sınıf örnekleri arasında.

(NOT: Bir sınıf örneği kendi sürümünü tanımlamaya karar vermedikçe, _i! Ama eğer birisi bunu yapmaya karar verirse, aldıklarını hak ediyorlar, değil mi ???)

Teknik olarak konuştuğuna dikkat et i hala bir 'statik değişken' değildir; bu bir propertyBu, özel bir tanımlayıcı türüdür. Ancak property Davranış artık tüm sınıf örneklerinde senkronize edilmiş (değişebilir) bir statik değişkene eşdeğerdir.

Ölümsüz "Statik Değişkenler"

Değişken statik değişken davranış için, sadece atlayın 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 örneği ayarlamaya çalışıyor i özellik bir AttributeError:

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

Bir Gotcha'nın farkında olmak

Yukarıdaki yöntemlerin yalnızca aşağıdakilerle çalıştığını unutmayın. örnekleri senin sınıfın değil iş 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'

Çizgi assert Test.i == x.i bir hata üretir, çünkü i özniteliği Test ve x iki farklı nesne vardır.

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

    i = property(get_i) 

Açıkçası üye i arasında Test bir olmalı property nesnesi, döndürülen nesnenin türü olan property işlevi.

Yukarıdaki kafa karıştırıcıyı bulursanız, muhtemelen diğer dillerin bakış açısından bunu düşünebilirsiniz (ör. Java veya c ++). Ders çalışmalısın property nesne, Python özniteliklerinin döndürülme sırası, tanımlayıcı protokolü ve yöntem çözümleme sırası (MRO).

Yukarıdaki 'gotcha' için bir çözüm sundum; ancak - yorucu bir şekilde - aşağıdaki gibi bir şey yapmayı denemediğinizi - en azından - iyice anlamanızı öneririm assert Test.i = x.i hataya neden olur.

GERÇEK, GERÇEK Statik Değişkenler - Test.i == x.i

Sadece bilgilendirme amaçlı (Python 3) çözümünü aşağıda sunuyoruz. Bunu "iyi bir çözüm" olarak onaylamıyorum. Python'daki diğer dillerin statik değişken davranışını taklit etmenin gerçekten gerekli olup olmadığı konusunda şüphelerim var. Ancak, aslında yararlı olup olmadığına bakılmaksızın, aşağıdakiler Python'un nasıl çalıştığı hakkında daha fazla bilgi sahibi olmalıdır.

GÜNCELLEME: bu girişim gerçekten çok berbat; Böyle bir şey yapmakta ısrar ederseniz (ipucu: lütfen yapmayın; Python çok zarif bir dildir ve başka bir dil gibi davranmaya yetmez), Ethan Furman'ın cevabı yerine.

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

Bir meta sınıf bir sınıfın sınıfıdır. Python'daki tüm sınıflar için varsayılan meta sınıf (yani, "yeni stil" sınıfları Python 2.3'ü post ediyor) 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 böyle uygulayın (sadece 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. Temel olarak varsayılan alıcı, ayarlayıcı ve delicinin, istenen özniteliğin "statik değişken" olup olmadığını kontrol eden sürümlerle değiştirerek çalışır.

"Statik değişkenler" kataloğunda saklanır. StaticVarMeta.statics bağlıyor. Tüm özellik istekleri başlangıçta bir yedek çözüm siparişi kullanılarak çözülmeye çalışılır. Bunu "statik çözünürlük sırası" veya "SRO" olarak adlandırdım. Bu, belirli bir sınıf (veya üst sınıfları) için "statik değişkenler" kümesinde istenen özniteliği arayarak yapılır. Öznitelik "SRO" içinde görünmüyorsa, sınıf varsayılan öznitelik get / set / delete davranışına (yani "MRO") geri dönecektir.

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

141
2017-12-19 15:16



Senin yolunu kullanmayı denedim ama bir problemle karşı karşıyayım, lütfen soruma bir bakın. stackoverflow.com/questions/29329850/get-static-variable-value - Muhammed Refaat
@RickTeachey: Genelde sınıf örneğinde yaptığınız her şeyi görmelisiniz Test (örneklerin oluşturulması için kullanmadan önce) meta-programlama alanında olduğu gibi? Örneğin, sınıf davranışını değiştirerek Test.i = 0 (burada sadece eşya nesnesini tamamen yok edin). Sanırım "mülkiyet mekanizması", bir sınıfın örneklerine yalnızca özellik erişimlerinde başlıyor (belki de bir ara sınıf olarak belki de altta yatan bir davranışı değiştirmediğiniz sürece). Btw, lütfen bu cevabı tamamlayın :-) - Ole Thomsen Buus
@RickTeachey Teşekkürler :-) Sonuçta metaclass ilginç ama aslında benim sevme için biraz fazla karmaşık. Bu mekanizmanın kesinlikle gerekli olduğu büyük bir çerçeve / uygulamada yararlı olabilir. Her neyse, bu, yeni (karmaşık) varsayılan olmayan meta-davranışa gerçekten ihtiyaç duyulursa, Python'un bunu mümkün kıldığını gösterir :) - Ole Thomsen Buus
@OleThomsenBuus: Çek cevabım işi yapan daha basit bir meta sınıf için. - Ethan Furman
@taper Doğru sizsiniz; Sorunu düzeltmek için cevabı düzenledim (çok uzun süre orada oturduğuna inanamıyorum!). Karışıklık için özür dilerim. - Rick Teachey


Sınıf değişkenlerini anında sinyale de 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]

23
2017-09-17 08:06



Yeni sınıf değişkenleri, sınıf başka bir modüle içe aktarılmış olsa bile yapışır mı? - zakdances
Evet. Sınıflar, onları adlandırdığınız ad alanı ne olursa olsun etkili bir şekilde tekildir. - Pedro


Şahsen statik bir yönteme ihtiyaç duyduğumda bir classmethod kullanırdım. Esas olarak 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 .. Zamanında bazı python tanımlarına bakın .. değişken her zaman değişebilir. Bunların iki türü değişebilir ve değişmez .. Ayrıca, sınıf özellikleri ve örnek nitelikleri vardır .. Hiçbir şey java & c ++ anlamda statik özellikleri gibi

Statik yöntemi pythonic anlamda kullanmalı, eğer derse karşı bir ilgisi yoksa! Senin yerinde olsaydım, ya sınıf metodunu kullanırdım ya da metodu sınıftan bağımsız olarak tanımlardım.


12
2017-09-16 02:02



Değişkenler değişmez veya değişmez değildir; nesneler. (Ancak, bir nesne, değişen derecelerde başarı ile, atamanın belirli özelliklerine göre atamayı önlemeye çalışabilir.) - Davis Herring


Pitonda statik yöntemler denir classmethods. 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

Yöntemi çağırdığımızda dikkat edin myInstanceMethod, bir hata alırız. Bunun nedeni, bu yöntemin bir örneğine çağrılmasını gerektirir. Yöntem myStaticMethod kullanarak bir classmethod olarak ayarlanır dekoratör  @classmethod.

Sadece tekmeler ve kıkırdaklar için myInstanceMethod sınıfın bir örneğini geçerek sınıfta, öyle:

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

11
2017-09-16 02:05





Aşağıdaki örnekte gösterilen statik özellikler ve örnek özellikleriyle ilgili dikkat 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, value örneğine değer atamadan önce, 'property' özelliğine erişmeye çalışırsak, statik değer kullanılır. Python sınıfında bildirilen her özellik, bellekte her zaman statik bir yuvaya sahiptir.


10
2018-03-08 06:06





Bazı üye değişkenlerini herhangi bir üye metodu dışında tanımlarken, değişken, değişkenin nasıl ifade edildiğine bağlı olarak statik veya statik olmayan olabilir.

  • CLASSNAME.var statik değişkendir
  • INSTANCENAME.var statik değişken değil.
  • sınıf içinde self.var statik değişken değildir.
  • sınıf elemanının içinde var olan fonksiyon tanımlanmamıştır.

Ö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

7
2018-03-26 17:56





Ayrıca, meta sınıfı kullanarak statik olmak için bir sınıfı da 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

Daha sonra ne zaman kaza ile başlatmaya çalışırsınız Sınıfım StaticClassError alırsınız.


6
2017-11-20 12:06



Bunu başlatamayacaksanız, neden bir sınıf bile? Bu, Python'u Java'ya dönüştürmek için bükülüyormuş gibi hissettiriyor .... - Ned Batchelder
Borg deyim Bu işlemek için daha iyi bir yoldur. - Rick Teachey


Sahip olmak mümkündür static sınıf değişkenleri, ama muhtemelen çabaya değmez.

İşte Python 3'te yazılmış bir kavram ispatıdır - tam ayrıntılardan herhangi biri yanlışsa, kod, sadece bir 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)

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

4
2018-03-25 09:02



Bu benim yukarıdaki girişimlerimden çok daha basit. Bravo! - Rick Teachey


Python'un öznitelik arayışıyla ilgili çok ilginç bir nokta, bunun yaratılmasında kullanılabileceğidir.gerçek değişkenler":

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, oluşturulduktan sonra bunlara atama yapılmaz. Aramanın kullandığını unutmayın. self çünkü, label bir ile ilişkili olmamak anlamında statiktir belirli Örnek, değer hala (sınıfın) örneğine bağlıdır.


4
2017-09-21 04:04