سؤال

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

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

المحلول

ربما قليلا من رمز المثال سوف تساعد:لاحظ الفرق في الدعوة تواقيع foo, class_foo و static_foo:

class A(object):
    def foo(self, x):
        print "executing foo(%s, %s)" % (self, x)

    @classmethod
    def class_foo(cls, x):
        print "executing class_foo(%s, %s)" % (cls, x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" % x    

a = A()

أدناه هي الطريقة المعتادة مثيل كائن يدعو الأسلوب.الكائن سبيل المثال ، a, هو ضمنا تمرير الوسيطة الأولى.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

مع classmethods, الفئة من كائن سبيل المثال ضمنيا تمرير الوسيطة الأولى بدلا من self.

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

يمكنك أيضا الاتصال class_foo باستخدام الفئة.في الواقع, إذا كنت تعرف شيئا أ classmethod ، ربما لأن كنت تنوي الاتصال من فئة بدلا من فئة سبيل المثال. A.foo(1) قد أثار TypeError ، ولكن A.class_foo(1) يعمل على ما يرام:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

استخدام واحد من الناس قد وجدت لفئة الطرق لإنشاء القابلة للتوريث البديلة المنشئات.


مع staticmethods, لا self (الكائن سبيل المثال) ولا cls (الطبقة) ضمنيا تمرير الوسيطة الأولى.يتصرفون مثل عادي الوظائف ما عدا ذلك يمكنك الاتصال بهم من مثيل أو الطبقة:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Staticmethods تستخدم مجموعة من الوظائف التي يكون بعض المنطقية اتصال مع فئة إلى فئة.


foo هو مجرد وظيفة ، ولكن عند استدعاء a.foo كنت لا مجرد الحصول على وظيفة ، يمكنك الحصول على "مطبق جزئيا" نسخة من وظيفة مع مثيل الكائن a لا بد كأول حجة على وظيفة. foo وتتوقع 2 الحجج ، في حين a.foo فقط تتوقع 1 الحجة.

a لا بد أن foo.هذا هو ما هو المقصود من مصطلح "الالتزام" أدناه:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

مع a.class_foo, a لا بد أن class_foo, بل فئة A لا بد أن class_foo.

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

هنا مع staticmethod, على الرغم من أنه هو الأسلوب ، a.static_foo يعود فقط جيدة 'ole وظيفة مع أي حجج ملزمة. static_foo وتتوقع 1 الحجة ، a.static_foo وتتوقع 1 الحجة أيضا.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

وطبعا نفس الشيء يحدث عند استدعاء static_foo مع الطبقة A بدلا من ذلك.

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

نصائح أخرى

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

A classmethod, من ناحية أخرى, هو الأسلوب الذي يحصل على تمرير الفصل كان يسمى ، أو فئة سبيل المثال كان يطلق على الحجة الأولى.وهذا مفيد عندما تريد طريقة مصنع فئة:لأنه يحصل على الدرجة الفعلية كان يطلق على الحجة الأولى ، يمكنك دائما إنشاء مثيل فئة الحق ، حتى عندما فرعية هي المعنية.نلاحظ على سبيل المثال كيف dict.fromkeys(), ، classmethod ، يعود مثيل فرعية عندما دعا على فئة فرعية:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

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

الرسمية الثعبان مستندات:

@classmethod

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

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

على @classmethod شكل دالة الديكور – انظر وصف تعريفات الدالة في وظيفة التعاريف للحصول على التفاصيل.

يمكن أن يطلق عليه إما على الطبقة (مثل C.f()) أو على سبيل المثال (مثل C().f()).على سبيل المثال هو تجاهل باستثناء فئتها.إذا الدرجة طريقة دعا المشتقة فئة مشتقة من فئة الكائن مرت كما الضمنية الحجة الأولى.

فئة أساليب مختلفة من C++ أو جافا أساليب ثابتة.إذا كنت تريد هؤلاء يا ترى staticmethod() في هذا القسم.

@staticmethod

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

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

على @staticmethod شكل دالة الديكور – انظر وصف تعريفات الدالة في وظيفة التعاريف للحصول على التفاصيل.

يمكن أن يطلق عليه إما على الطبقة (مثل C.f()) أو على سبيل المثال (مثل C().f()).على سبيل المثال هو تجاهل باستثناء فئتها.

أساليب ثابتة في بيثون هي مماثلة إلى تلك التي وجدت في Java أو C++.عن أكثر تقدما المفهوم ، انظر classmethod() في هذا القسم.

هنا هي مقالة قصيرة على هذا السؤال

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

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

أن تقرر ما إذا كان استخدام @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 في الثعبان ؟

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

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 في هذه السلسلة ، للانضمام إلى آخر iterable, فإنه من الواضح تماما هو دالة على سبيل المثال ، بالإضافة إلى كونها دالة على iterable القائمة ، ['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 وحدة في بيثون 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}

في بيثون 2, يمكنك استيراد هذه الوظيفة من نحو متزايد أقل فائدة وحدة سلسلة:

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

طريقة الطبقة

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

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

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

عندما كنا فرعية ديكت ، يمكننا استخدام نفس المنشئ ، مما يخلق مثيل فرعية.

>>> 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 و staticmethod.

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

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

دعونا النظر لدينا Person الطبقة التي تحيط اثنين من الحجج first_name و last_name ويخلق مثيل Person.

class Person(object):

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

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

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

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, "")

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

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

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

و هل يمكن ببساطة الاتصال باستخدام class name

Person.validate_name("Gaurang Shah")

@ديكور أضيفت في بيثون 2.4 إذا كنت تستخدم بايثون < 2.4 يمكنك استخدام classmethod() و staticmethod() وظيفة.

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

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

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

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

اعتقد ان السؤال هو "متى يمكنك استخدام @classmethod vs @staticmethod?"

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

@staticmethod يوفر هامشية المكاسب الأداء, ولكن إلى الآن لم أرى الإنتاجية استخدام أسلوب ثابت ضمن الفئة التي لا تتحقق بذاتها وظيفة خارج الصف.

أساليب ثابتة:

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

فوائد أساليب ثابتة:

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

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

أساليب الفئة:

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

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

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

>>> 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 لديه وقت الحمل ولكن يجعل من الممكن الوصول إلى امتلاك الطبقة.وبدلا من ذلك فإنني أوصي باستخدام metaclass ووضع أساليب الفئة على أن metaclass:

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

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

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

  • الثعبان لا مثيل بد-طريقة كائن.
  • انه يخفف من قراءة رمز و لا تعتمد على حالة الكائن نفسه ؛

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

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

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

التشابه: كل منهم يمكن أن يطلق على الدرجة نفسها, بدلا من مجرد سبيل المثال من الطبقة.لذلك كلاهما في المعنى هي فئة أساليب.

الفرق: أ classmethod سوف تحصل على الدرجة نفسها الحجة الأولى ، في حين staticmethod لا.

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

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

وهناك اعتبار آخر فيما يتعلق staticmethod مقابل classmethod يأتي مع الميراث.نقول لديك فئة التالية:

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

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

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

يعمل هذا, لكن لاحظ أنه الآن bar() التنفيذ في الطبقة الطفل (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 التغييرات يجب أن نتذكر أن هذا التحديث 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

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

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 - أسلوب ثابت لا يمكن الاتصال الذاتي الطريقة ولكن يمكن الاتصال الأخرى ثابتة classmethod

3 - أسلوب ثابت تنتمي إلى فئة لن تستخدم كائن على الإطلاق.

4 - أسلوب فئة ليست ملزمة إلى كائن ولكن إلى فئة.

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

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

مساهمتي يوضح الفرق بين @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)
'''
"""

أساليب الفئة ، كما يوحي اسمها ، تستخدم لإجراء تغييرات على الطبقات وليس الكائنات.لإجراء تغييرات على الطبقات ، وسوف تعديل سمات الطبقة(لا سمات كائن) ، لأن هذا هو كيف يمكنك تحديث الطبقات.هذا هو السبب في أن أساليب الفئة الفئة(تقليديا تدل 'cls') كما في الحجة الأولى.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

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

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

قد ترغب في النظر في الفرق بين:

Class A:
    def foo():  # no self parameter, no decorator
        pass

و

Class B:
    @staticmethod
    def foo():  # no self parameter
        pass

هذا قد تغير بين python2 و python3:

python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

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

الحالات الأخرى قد تم تغطيتها جيدا قبل unutbus الإجابة.

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

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

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

الجواب القصير.الحجة الأولى:

  • طبيعي الطريقة:الحجة الأولى هي الكائن الحالي
  • classmethod:الحجة الأولى هي فئة الكائن الحالي
  • staticmethod:الحجة الأولى هي إزالة

أطول الجواب:

عادي طريقة

عندما كائن هو ما يسمى طريقة, هو تلقائيا نظرا حجة اضافية self كما في الحجة الأولى.هذا هو الأسلوب

def f(self, x, y)

يجب أن يكون طالب مع 2 الحجج. self يتم تمرير تلقائيا ، ومن الكائن نفسه.

طريقة الطبقة

عند طريقة تزيين

@classmethod
def f(cls, x, y)

تلقائيا شريطة الحجة لا self, ولكن فئة self.

أسلوب ثابت

عند طريقة تزيين

@staticmethod
def f(x, y)

طريقة لا يعطى أي التلقائي حجة على الإطلاق.هو فقط إعطاء المعلمات التي ويسمى مع.

الأعراف

  • classmethod تستخدم في الغالب بديل المنشئات.
  • staticmethod لا تستخدم الدولة من وجوه.يمكن أن تكون وظيفة الخارجية إلى فئة.إلا أنها وضعت داخل الصف تجميع الوظائف مع وظائف مماثلة (على سبيل المثال ، مثل جافا Math فئة أساليب ثابتة)
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top