python - ما الفرق بينstaticmethod وclassmethod؟




oop methods (16)

ما الفرق بينstaticmethod وclassmethod في بايثون؟

ربما تكون قد رأيت رمز Python مثل هذا pseudocode ، والذي يوضح توقيعات أنواع الطرق المختلفة ويوفر توثيقًا لشرح كل منها:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

أسلوب المثيل العادي

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

على سبيل المثال ، هذه نسخة من سلسلة:

', '

إذا استخدمنا طريقة المثيل ، join إلى هذه السلسلة ، للانضمام إلى أمر آخر ، فمن الواضح أنه دالة للمثيل ، بالإضافة إلى كونه دالة للقائمة المتكرّرة ، ['a', 'b', 'c'] :

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

طرق ملزمة

يمكن ربط أساليب المثيل عبر بحث منقط للاستخدام لاحقًا.

على سبيل المثال ، هذا يربط طريقة str.join ':' :

>>> join_with_colons = ':'.join 

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

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

طريقة ثابتة

لا تأخذ الطريقة الثابتة المثيل كوسيطة.

وهو مشابه جدًا لوظيفة مستوى الوحدة النمطية.

ومع ذلك ، يجب أن تعمل وظيفة مستوى الوحدة النمطية في الوحدة النمطية ويتم استيرادها خصيصًا إلى أماكن أخرى حيث يتم استخدامها.

إذا كان متصلاً بالكائن ، فسيتبع ذلك الشيء بشكل ملائم من خلال الاستيراد والوراثة أيضًا.

مثال على طريقة ثابتة هي str.maketrans ، تم نقلها من الوحدة النمطية string في Python 3. إنها تجعل جدول الترجمة مناسبًا للاستهلاك بواسطة str.translate . يبدو الأمر سخيفًا عند استخدامه من مثيل لسلسلة ، كما هو موضح أدناه ، ولكن استيراد الدالة من الوحدة النمطية string هو بالأحرى خرقاء ، ومن الجيد أن تتمكن من الاتصال به من الفصل ، كما هو الحال في str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

في python 2 ، يجب عليك استيراد هذه الدالة من الوحدة النمطية سلسلة غير مفيدة بشكل متزايد:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

طريقة الفصل

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

المثال الأكثر اقتراحا من classmethod مدمج هو dict.fromkeys . يتم استخدامه كمنشئ بديل لل dict ، (مناسبة تمامًا عندما تعرف ما هي مفاتيحك وتريد قيمة افتراضية لها.)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

عندما نستخدم الفئة الفرعية dict ، يمكننا استخدام نفس المُنشئ ، مما يؤدي إلى إنشاء مثيل للفئة الفرعية.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

انظر رمز مصدر الباندا لأمثلة أخرى مماثلة من classmethod البديلة ، وانظر أيضا وثائق بيثون الرسمية على classmethod و staticmethod .

ما هو الفرق بين وظيفة مزينة بـ @staticmethod وواحدة مزينة بـ @classmethod ؟


classmethod: يمكن استخدامه لإنشاء وصول عالمي مشترك إلى جميع الأمثلة التي تم إنشاؤها من هذا الصنف ..... مثل تحديث سجل من قبل مستخدمين متعددين .... أنا وجدت بشكل خاص أنها تستخدم فول عند إنشاء singletons كذلك ..: )

الأسلوبstatic: لا علاقة له بالفئة أو المثيل المرتبط بـ ... ولكن للقراءة يمكن أن تستخدم طريقة ثابتة


اسمحوا لي أن أقول التشابه بين طريقة مزينة @ classmethod مقابل @ staticmethod أولا.

التشابه: يمكن استدعاء كلاهما على Class نفسه ، بدلاً من مثيل الطبقة فقط. إذن ، كلاهما بمعنى ما هي أساليب الفصل .

الفرق: سيحصل الطبقة الطبقية على الطبقة نفسها كحجة أولى ، في حين أن staticmethod لا يحصل عليها.

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

class C(object):
    @classmethod
    def fun(cls, arg1, arg2, ...):
       ....

fun: function that needs to be converted into a class method
returns: a class method for function.

بدأت تعلم لغة البرمجة مع C ++ ومن ثم Java ثم Python ولذلك أزعجني هذا السؤال كثيرًا حتى فهمت الاستخدام البسيط لكل منهما.

طريقة Class: لا تملك Python بخلاف Java و C ++ تحميل زائد منشئ. ومن أجل تحقيق ذلك ، يمكنك استخدام classmethod . المثال التالي سوف يفسر هذا

لنفترض أن لدينا فصل Person يأخذ first_name و last_name مثيل الشخص.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

الآن ، إذا جاء المتطلب حيث تحتاج إلى إنشاء فصل باستخدام اسم واحد فقط ، فقط first_name ، لا يمكنك فعل شيء كهذا في python.

سيعطيك هذا خطأ عندما تحاول إنشاء كائن (مثيل).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

ومع ذلك ، يمكنك تحقيق نفس الشيء باستخدام @classmethod كما هو مذكور أدناه

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

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

لنفترض في المثال أعلاه أنك تحتاج إلى التحقق من أن أولًا ، يجب ألا يتجاوز 20 حرفًا ، يمكنك القيام بذلك ببساطة.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

ويمكنك ببساطة الاتصال باستخدام اسم الفصل

Person.validate_name("Gaurang Shah")

سأحاول شرح الفرق الأساسي باستخدام مثال.

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - يمكننا الاتصال بشكل مباشر و classmethods دون التهيئة

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- لا يمكن للطريقة الساكنة أن تستدعي طريقة ذاتية ، ولكن يمكن أن تستدعي ثباتًا ثابتًا وطبقات أخرى

3 - طريقة ثابتة تنتمي إلى الطبقة ولن تستخدم أي شيء على الإطلاق.

4 - لا ترتبط طريقة الفئة بأحد الأشياء بل بالفئة.


في الأساس ، يجعل @classmethod طريقة تكون @classmethod الأولى هي الفئة التي يتم استدعاؤها من (بدلاً من مثيل الفئة) ، لا @staticmethod على أي حجج ضمنية.


لتحديد ما إذا كنت تريد استخدام @staticmethod أو @classmethod عليك أن تنظر إلى داخل طريقتك. إذا وصلت طريقتك إلى متغيرات / طرق أخرى في صفك ، فاستخدمclassmethod . من ناحية أخرى ، إذا لم تلمس طريقتك أي أجزاء أخرى من الفصل ، فاستخدمstaticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1

نظرة أخرى فيما يتعلق staticmethod مقابل classmethod يأتي مع الميراث. لنفترض أن لديك الفصل التالي:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

ثم تريد تجاوز bar() في فئة فرعية:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

يعمل هذا ، ولكن لاحظ أن الآن تطبيق bar() في فئة Foo2 ( Foo2 ) لم يعد قادراً على الاستفادة من أي شيء محدد إلى تلك الفئة. على سبيل المثال ، لنفترض أن Foo2 كان Foo2 على طريقة تسمى magic() التي تريد استخدامها في تطبيق Foo2 bar() :

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

سيكون الحل هنا هو الاتصال بـ Foo2.magic() في bar() ، ولكن بعد ذلك تقوم بتكرار نفسك (إذا تغير اسم Foo2 ، Foo2 عليك تذكر تحديث هذا الأسلوب bar() ).

بالنسبة لي ، يعد هذا انتهاكًا بسيطًا للمبدأ المفتوح / المغلق ، لأن القرار المتخذ في Foo يؤثر على قدرتك على إعادة ترميز الشفرة الشائعة في فئة مكتسبة (أي أنه أقل انفتاحًا على الإضافة). إذا كان bar() نوعًا ما ، classmethod بخير:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

يعطي: In Foo2 MAGIC


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

@staticmethod وظيفة ليست أكثر من وظيفة محددة داخل الطبقة. هو قابل للاستدعاء دون إنشاء الدرجة الأولى. إنه تعريف ثابت من خلال الميراث.

  • ليس لدى Python إلى إنشاء طريقة مقيد للكائن.
  • أنه يخفف من سهولة قراءة التعليمات البرمجية ، ولا يعتمد على حالة الكائن نفسه ؛

@classmethod وظيفة @classmethod قابلة للاستدعاء أيضًا دون إنشاء الطبقة ، لكن تعريفها يتبع فئة فرعية ، وليس فئة الوالدين ، عن طريق الوراثة ، يمكن تجاوزها بواسطة الفئة الفرعية. هذا لأن الحجة الأولى لوظيفة @classmethod يجب أن تكون دائما cls (class).

  • أساليب المصنع ، التي يتم استخدامها لإنشاء مثيل لفئة ما ، على سبيل المثال ، نوعًا ما من المعالجة المسبقة.
  • الطرق الثابتة التي تستدعي أساليب ثابتة : إذا قمت بتقسيم أساليب ثابتة في عدة طرق ثابتة ، فلا يجب عليك ترميز اسم الفئة ولكنك تستخدم أساليب الفصل

@staticmethod فقط يعطل الوظيفة الافتراضية كما واصف الأسلوب. classmethod يلتف الدالة الخاصة بك في حاوية callable الذي يمرر مرجع إلى فئة المالك كوسيطة الأولى:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

كما واقع الأمر ، classmethod لديه النفقات العامة runtime ولكن يجعل من الممكن للوصول إلى الطبقة امتلاك. بدلا من ذلك أوصي باستخدام metaclass ووضع أساليب الطبقة على هذا metaclass:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

طرق ثابتة:

  • وظائف بسيطة مع عدم وجود حجة النفس.
  • العمل على الصف السمات. لا على سبيل المثال الصفات.
  • يمكن استدعاؤها من خلال كل من الطبقة والمثيل.
  • يتم استخدام staticmethod () الدالة المضمنة في إنشائها.

فوائد الطرق الثابتة:

  • فإنه يعرّف اسم الدالة في classscope
  • يحرك رمز الوظيفة أقرب إلى حيث يتم استخدامها
  • أكثر ملاءمة للاستيراد مقابل وظائف مستوى الوحدة النمطية لأن كل طريقة لا يجب أن تكون مستوردة بشكل خاص

    @staticmethod
    def some_static_method(*args, **kwds):
        pass
    

طرق الطبقة:

  • الدالات التي تحتوي على الوسيطة الأولى باعتبارها classname.
  • يمكن استدعاؤها من خلال كل من الطبقة والمثيل.
  • يتم إنشاء هذه مع وظيفة classmethod في بني.

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    

طريقة الطبقة مقابل طريقة ثابتة في بايثون

طريقة الفصل

المصممclassmethod ، هو مصمم ديكور مدمج هو تعبير يتم تقييمه بعد تعريف الدالة الخاصة بك. نتيجة هذا التقييم تظليل تعريف الدالة الخاصة بك.

يتلقى أسلوب الفئة فئة كوسيطة ضمنية الأول ، تماماً مثل أسلوب مثيل يتلقى المثيل

بناء الجملة:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • طريقة الفصل هي طريقة مرتبطة بالفئة وليس موضوع الفصل.
  • لديهم الوصول إلى حالة الفصل لأنه يأخذ معلمة فئة يشير إلى الفئة وليس مثيل الكائن.
  • يمكن أن يقوم بتعديل حالة الفصل التي سيتم تطبيقها في جميع مراحل الفصل. على سبيل المثال ، يمكن تعديل متغير صنف قابل للتطبيق على كل المثيلات.

طريقة ثابتة

لا يتلقى الأسلوب الثابت وسيطة أولى ضمنية.

بناء الجملة:

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)
  • الطريقة الثابتة هي أيضًا طريقة مرتبطة بالفئة وليس كائن الفصل.
  • لا يمكن للطريقة الثابتة الوصول إلى حالة الفصل الدراسي أو تعديلها.
  • وهو موجود في الفصل لأنه من المنطقي أن تكون الطريقة موجودة في الفصل.

طريقة Class vs Static Method

  • تأخذ طريقة الفئة cls كمعلمة أولية بينما لا يحتاج الأسلوب الثابت إلى معلمات محددة.
  • يمكن لطريقة الفصل الوصول إلى حالة الفصل الدراسي أو تعديلها بينما لا يمكن للطريقة الثابتة الوصول إلى أو تعديلها.
  • نستخدم مصمم ديكورclassmethod في python لإنشاء طريقة للفصل الدراسي ونستخدم @ styaticmethod لإنشاء طريقة ثابتة في python.

متى تستخدم ماذا؟

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

كيفية تحديد طريقة الصف وطريقة ثابتة؟

لتحديد طريقة صنف في python ، نستخدم decorator @ classmethod ونحدد طريقة ثابتة نستخدمها @ styaticmethod decorator.

دعونا ننظر إلى مثال لفهم الفرق بين كل منهما. دعنا نقول أننا نريد إنشاء فئة شخص. الآن ، لا يدعم python التحميل الزائد للطريقة مثل C ++ أو Java لذا نستخدم طرق الفصل لإنشاء طرق المصنع. في المثال التالي ، نستخدم طريقة صنف لإنشاء كائن شخص من سنة الميلاد.

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

التنفيذ

21
21
True

انتاج |

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

Reference


تبرهن مساهمتي على الفرق بين @classmethod، @staticmethodوعلى سبيل المثال ، الطرق ، بما في ذلك كيف يمكن للمثيل أن يدعو بطريقة غير مباشرة @staticmethod. ولكن بدلاً من الاتصال بطريقة غير مباشرة @staticmethodمن مثيل ، قد يكون جعله خاصًا أكثر "pythonic". لم يتم توضيح كيفية الحصول على شيء ما من طريقة خاصة ، ولكنه في الأساس نفس المفهوم.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

تحليلstaticmethod تقديم حرفيا رؤى مختلفة.

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

في الواقع ، تعتبر staticmethod دالة عادية مماثلة لتلك الموجودة خارج تعريف الفئة.
إنه لحسن الحظ تجميعها في الصف فقط من أجل الوقوف بشكل أقرب حيث يتم تطبيقه ، أو يمكنك التمرير للعثور عليه.


ويكشف الاختراق السريع لطرق مماثلة في iPython عن @staticmethodتحقيق مكاسب هامشية في الأداء (في النانوسيكند) ، ولكن بخلاف ذلك يبدو أنه لا يخدم أي وظيفة. أيضا ، من المحتمل أن يتم محو أي مكاسب في الأداء من خلال العمل الإضافي لمعالجة الطريقة staticmethod()خلال التحويل البرمجي (الذي يحدث قبل تنفيذ أي تعليمات برمجية عند تشغيل برنامج نصي).

من أجل قراءة التعليمات البرمجية ، يجب تجنب @staticmethodما لم يتم استخدام الطريقة الخاصة بك لأحمال العمل ، حيث يتم حساب النانوسيكند.


#!/usr/bin/python
#coding:utf-8

class Demo(object):
    def __init__(self,x):
        self.x = x

    @classmethod
    def addone(self, x):
        return x+1

    @staticmethod
    def addtwo(x):
        return x+2

    def addthree(self, x):
        return x+3

def main():
    print Demo.addone(2)
    print Demo.addtwo(2)

    #print Demo.addthree(2) #Error
    demo = Demo(2)
    print demo.addthree(2)


if __name__ == '__main__':
    main()




python-decorators