سؤال

هل من الممكن أن يكون ثابت الدرجة المتغيرات أو أساليب في الثعبان ؟ ما الجملة هو المطلوب أن أفعل هذا ؟

هل كانت مفيدة؟

المحلول

المتغيرات أعلن الداخل تعريف الفئة ، ولكن ليس داخل الطريقة هي الطبقة أو متغيرات ثابتة:

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

كما @millerdev يشير هذا يخلق مستوى الفئة i متغير, ولكن هذا يختلف عن أي مثيل على مستوى i متغير, لذلك يمكن أن يكون

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

وهذا يختلف عن C++ و Java, ولكن لا يختلف كثيرا عن C#, حيث ثابت عضو لا يمكن الوصول إليها باستخدام إشارة إلى مثيل.

انظر ما بيثون البرنامج التعليمي حول هذا الموضوع من الطبقات كائنات فئة.

@ستيف جونسون قد أجبت فيما يتعلق أساليب ثابتة, كما وثقت تحت "المدمج في وظائف" في بيثون مكتبة مرجعية.

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

@beidy توصي classmethods على staticmethod, طريقة ثم يتلقى نوع من الدرجة الأولى حجة, ولكن أنا لا يزال غامض قليلا على مزايا هذا النهج على staticmethod.إذا كنت أيضا, ثم ربما لا يهم.

نصائح أخرى

@بلير كونراد قال متغيرات ثابتة أعلن الداخل تعريف الفئة ، ولكن ليس داخل الطريقة هي الطبقة أو "ثابت" المتغيرات:

>>> 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 مساحة الاسم.إذا كنت ترغب في تغيير قيمة "ثابت" متغير ، يجب تغييره ضمن نطاق (أو كائن) حيث كان يعرف أصلا.وضعت "ثابت" في الاقتباس لأن الثعبان لا يملك متغيرات ثابتة بمعنى أن C++ و Java القيام به.

على الرغم من أنه لا يقول أي شيء محدد حول متغيرات ثابتة أو الأساليب ، بيثون التعليمي لديه بعض المعلومات ذات الصلة دروس و كائنات فئة.

@ستيف جونسون أيضا أجاب بشأن أساليب ثابتة, كما وثقت تحت عنوان "المدمج في وظائف" في بيثون مكتبة مرجعية.

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

@beid كما ذكر classmethod ، الذي يشبه 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(), أي من الحجج التي لا بد و وجود الحجج في كل ما هو اختياري.

"متغيرات ثابتة"

ومع ذلك ، فإن تنفيذ "متغيرات ثابتة" (حسنا ، قابلة للتغيير متغيرات ثابتة ، على أي حال ، إذا كان هذا لا تناقض في الشروط...) ليست مستقيمة.كما millerdev أشار في جوابه, المشكلة أن بايثون سمات الطبقة ليست حقا "متغيرات ثابتة".النظر:

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 وأضاف مثيل جديد السمة i إلى x بدلا من تغيير قيمة 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

واحد مسكتك أن تكون على علم

علما أن الأساليب المذكورة أعلاه تعمل فقط مع الحالات من الفئة الخاصة بك -- أنها سوف لا العمل عند استخدام الطبقة نفسها.لذلك على سبيل المثال:

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 نوعان مختلفان من الكائنات.

كثير من الناس سوف تجد هذه مثيرة للدهشة.بيد أنه لا ينبغي أن يكون.إذا عدنا وتفتيش لدينا Test تعريف الفئة (النسخة الثانية), ونلاحظ من هذا السطر:

    i = property(get_i) 

ومن الواضح الأعضاء i من Test يجب أن يكون property الكائن الذي هو نوع الكائن عاد من property وظيفة.

إذا يمكنك العثور أعلاه مربكة ، أنت على الأرجح لا يزال التفكير في الأمر من وجهة نظر لغات أخرى (مثلا ، Java أو c++).يجب أن تذهب دراسة property الكائن عن الترتيب الذي بيثون سمات عاد ، واصف البروتوكول ، وطريقة القرار من أجل (MRO).

أقدم حلا فوق 'زورو' أدناه ؛ ومع ذلك أود أن أقترح - بشدة - أن لا تحاول أن تفعل شيئا مثل التالية حتى - في الحد الأدنى - هل نفهم جيدا لماذا assert Test.i = x.i يتسبب خطأ.

حقيقية متغيرات ثابتة - Test.i == x.i

أقدم لكم (بيثون 3) حل أدناه لأغراض إعلامية فقط.أنا لست مؤيدا ذلك بأنه "حل جيد".لدي شكوك فيما إذا كان يحاكي ثابت متغير السلوك من اللغات الأخرى في بيثون هو من أي وقت مضى في الواقع ضرورية.ومع ذلك ، بغض النظر عما إذا كان هو في الواقع مفيدة ، أدناه ينبغي أن تساعد على زيادة فهم كيفية بايثون يعمل.

تحديث:هذه المحاولة هو حقا فظيعة جدا;إذا كنت تصر على القيام بشيء من هذا القبيل (تلميح:من فضلك لا ؛ بيثون هي أنيقة جدا لغة الحذاء يتدخل في التصرف مثل لغة أخرى فقط غير ضروري), استخدام التعليمات البرمجية في إيثان فرمان الجواب بدلا من ذلك.

محاكاة ثابت متغير السلوك من لغات أخرى باستخدام metaclass

أ metaclass هي فئة من فئة.الافتراضي metaclass لجميع الطبقات في بيثون (أي "نمط جديد" الطبقات بعد بيثون 2.3 أعتقد) هو type.على سبيل المثال:

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

ومع ذلك ، يمكنك تحديد الخاصة بك metaclass مثل هذا:

class MyMeta(type): pass

وتطبيقه على الفئة الخاصة بك عن مثل هذا (بيثون 3 فقط):

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

وفيما يلي metaclass لقد خلق الذي يسعى لمحاكاة "متغير ثابت" السلوك من اللغات الأخرى.انها في الأساس يعمل عن طريق استبدال الافتراضي جالبة, اضع, و deleter مع الإصدارات التي تحقق لمعرفة ما إذا كانت السمة المطلوب هو "متغير ثابت".

كتالوج "متغيرات ثابتة" يتم تخزينها في StaticVarMeta.statics السمة.كل سمة الطلبات في البداية حاول أن تحل باستخدام بديلا قرار النظام.لقد أطلق على هذا "قرار ثابت النظام" ، أو "المؤسسة".ويتم ذلك من خلال البحث عن طلب السمة في مجموعة من "متغيرات ثابتة" لفئة معينة (أو الأم الطبقات).إذا كانت السمة لا تظهر في "المؤسسة" ، فئة سوف يرتد على السمة الافتراضية الحصول على/مجموعة/حذف السلوك (أي "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]

شخصيا أود أن استخدام classmethod كلما كنت في حاجة إلى أسلوب ثابت.أساسا لأن أحصل على الدرجة كحجة.

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

أو استخدام الديكور

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

على خصائص ثابتة..وقتها كنت ابحث عن بعض الثعبان التعريف..متغير يمكن دائما تغيير.هناك نوعان منها قابلة للتغيير وغير قابل للتغيير..أيضا ، هناك سمات الطبقة وعلى سبيل المثال الصفات..لا شيء حقا مثل سمات ثابتة في معنى java & c++

لماذا استخدام أسلوب ثابت في pythonic المعنى ، إذا كان لديه أي كل ما يتعلق الدرجة!إذا كنت تريد استخدام إما classmethod أو تحديد طريقة المستقلة من الفئة.

شيء خاص واحد أن نلاحظ حول خصائص ثابتة & خصائص المثال ، كما هو موضح في المثال أدناه:

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

هذا يعني قبل تعيين القيمة إلى الملكية سبيل المثال ، إذا حاولنا الوصول إلى الملكية من خلال' سبيل المثال ، فإن قيمة ثابتة يتم استخدامها. كل الممتلكات أعلن في بيثون فئة دائما ثابتة فتحة في الذاكرة.

أساليب ثابتة في بيثون تسمى classmethods.نلقي نظرة على التعليمات البرمجية التالية

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 باستخدام الديكور @classmethod.

فقط من أجل المرح و الضحك, يمكن أن نسميه myInstanceMethod على الطبقة عن طريق تمرير في مثيل من فئة مثل:

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

عند تحديد بعض الأعضاء متغير خارج أي عضو طريقة متغير يمكن أن تكون إما ثابتة أو غير ثابتة اعتمادا على كيفية متغير يعبر عنها.

  • CLASSNAME.فار هو متغير ثابت
  • INSTANCENAME.فار ليست ثابتة ومتغيرة.
  • النفس.فار داخل الطبقة ليست ثابتة ومتغيرة.
  • فار داخل الطبقة وظيفة عضو لم يتم تعريف.

على سبيل المثال:

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

هل يمكن أيضا فرض فئة أن تكون ثابتة باستخدام metaclass.

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.

فمن الممكن أن يكون static فئة المتغيرات ، ولكن ربما لا يستحق كل هذا الجهد.

وهنا إثبات صحة مفهوم مكتوبة في بيثون 3 -- إذا كان أي من التفاصيل الدقيقة هي خطأ رمز يمكن أنب أن تتطابق تماما عن ما تقصد static variable:


class Static:
    def __init__(self, value, doc=None):
        self.deleted = False
        self.value = value
        self.__doc__ = doc
    def __get__(self, inst, cls=None):
        if self.deleted:
            raise AttributeError('Attribute not set')
        return self.value
    def __set__(self, inst, value):
        self.deleted = False
        self.value = value
    def __delete__(self, inst):
        self.deleted = True

class StaticType(type):
    def __delattr__(cls, name):
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            obj.__delete__(name)
        else:
            super(StaticType, cls).__delattr__(name)
    def __getattribute__(cls, *args):
        obj = super(StaticType, cls).__getattribute__(*args)
        if isinstance(obj, Static):
            obj = obj.__get__(cls, cls.__class__)
        return obj
    def __setattr__(cls, name, val):
        # check if object already exists
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            obj.__set__(name, val)
        else:
            super(StaticType, cls).__setattr__(name, val)

و في الاستخدام:

class MyStatic(metaclass=StaticType):
    """
    Testing static vars
    """
    a = Static(9)
    b = Static(12)
    c = 3

class YourStatic(MyStatic):
    d = Static('woo hoo')
    e = Static('doo wop')

وبعض الاختبارات:

ms1 = MyStatic()
ms2 = MyStatic()
ms3 = MyStatic()
assert ms1.a == ms2.a == ms3.a == MyStatic.a
assert ms1.b == ms2.b == ms3.b == MyStatic.b
assert ms1.c == ms2.c == ms3.c == MyStatic.c
ms1.a = 77
assert ms1.a == ms2.a == ms3.a == MyStatic.a
ms2.b = 99
assert ms1.b == ms2.b == ms3.b == MyStatic.b
MyStatic.a = 101
assert ms1.a == ms2.a == ms3.a == MyStatic.a
MyStatic.b = 139
assert ms1.b == ms2.b == ms3.b == MyStatic.b
del MyStatic.b
for inst in (ms1, ms2, ms3):
    try:
        getattr(inst, 'b')
    except AttributeError:
        pass
    else:
        print('AttributeError not raised on %r' % attr)
ms1.c = 13
ms2.c = 17
ms3.c = 19
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
MyStatic.c = 43
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19

ys1 = YourStatic()
ys2 = YourStatic()
ys3 = YourStatic()
MyStatic.b = 'burgler'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
assert ys1.d == ys2.d == ys3.d == YourStatic.d
assert ys1.e == ys2.e == ys3.e == YourStatic.e
ys1.a = 'blah'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
ys2.b = 'kelp'
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
ys1.d = 'fee'
assert ys1.d == ys2.d == ys3.d == YourStatic.d
ys2.e = 'fie'
assert ys1.e == ys2.e == ys3.e == YourStatic.e
MyStatic.a = 'aargh'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a

واحد نقطة مثيرة جدا للاهتمام حول بايثون السمة البحث هو أنه يمكن استخدامها لإنشاء "الظاهري المتغيرات":

class 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

إلقاء نظرة على هذا الجواب و المستندات الرسمية HOWTO لمزيد من المعلومات حول واصفات.

نعم بالتأكيد ، الثعبان في حد ذاته لم يكن لديك أي بيانات ثابتة الأعضاء صراحة ، ولكننا يمكن أن يكون قبل ذلك

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"

لتجنب أي التباس محتمل ، أود أن التباين متغيرات ثابتة و غير قابلة للتغيير الكائنات.

بعض أنواع الكائنات البدائية مثل الأعداد الصحيحة, العوامات, سلاسل, و touples هي ثابتة في بيثون.وهذا يعني أن الكائن الذي يشار إليه بواسطة اسم معين لا يمكن أن تتغير إذا كان واحد من المذكور أنواع الكائنات.اسم يمكن إعادة تعيين إلى وجوه مختلفة ، ولكن هدف في حد ذاته قد لا تكون تغيرت.

صنع متغير ثابت يأخذ هذه خطوة أخرى إلى الأمام عن طريق عدم السماح اسم المتغير للإشارة إلى أي كائن ولكن هذا الذي هو عليه حاليا نقطة.(ملاحظة:هذا هو برنامج مفهوم و غير محددة الثعبان;يرجى الاطلاع على مشاركات الآخرين للحصول على معلومات حول تنفيذ السكون في بيثون).

أفضل طريقة وجدتها هي استخدام فئة أخرى.يمكنك إنشاء كائن ومن ثم استخدامها في الكائنات الأخرى.

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 فئة تمثل الدرجة العادية نحن بحاجة إلى استخدام.

الآن أنا جعلت كائن واحد العلم (staticFlag).هذا العلم سوف يتم إرسال إشارة إلى جميع الأشياء العادية.

كل هذه الأشياء يتم إضافة إلى قائمة tryArr.


هذا البرنامج النصي النتائج:

False
False
False
False
False
True
True
True
True
True

نعم بالتأكيد من الممكن كتابة متغيرات ثابتة وأساليب في بيثون.

متغيرات ثابتة : أعلن متغير على مستوى الفئة تسمى متغير ثابت والتي يمكن الوصول إليها مباشرة باستخدام اسم الفئة.

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

أساليب ثابتة: مماثلة لتلك المتغيرات ، أساليب ثابتة يمكن الوصول إليها مباشرة باستخدام اسم الفئة.لا تحتاج إلى إنشاء مثيل.

ولكن نأخذ في الاعتبار أسلوب ثابت لا يمكن استدعاء غير أسلوب ثابت في بيثون.

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