@Staticmethod və @classmethod arasında fərq nədir?

@staticmethod və digər @classmethod ilə bəzədilmiş funksiya arasındakı fərq nədir?

2924
26 сент. Daryl Spitzer tərəfindən qoyulan 26 sentyabr. 2008-09-26 00:01 '08 at 0:01 2008-09-26 00:01
@ 26 cavab

Bəlkə bir az nümunə kodu kömək edəcək: foo , class_foostatic_foo çağırış imza fərqini qeyd edin:

 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)"%xa=A() 

Aşağıda, bir obyektin nümunəsi bir üsul adlandırdığı adi bir üsuldur. Bir obyektin a nümunəsi ilk arqument kimi örtük olaraq qəbul edilir.

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

Sinif metodlarını istifadə edərək, bir obyekt nümunəsi sinifi self əvəzinə ilk arqument kimi gizli şəkildə ötürülür.

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

Bir sinifdən istifadə etməklə də class_foo bilərsiniz. Əslində, əgər sinif metodunun lazım olan bir şeyi müəyyənləşdirsəniz, ehtimal ki, bir sinifdən deyil, sinifdən bir nümunədən çağırmaq niyyətindəsiniz. A.foo(1) TypeError çağırır, amma A.class_foo(1) işləyir:

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

İnsanlar tərəfindən istifadə edilən sinif üsullarından biri, miras alınmış alternativ qurucular yaratmaqdır.


Statik metodlarla, nə ilk növbədə self (obyektin nümunəsi), nə də cls (sinif) örtük olaraq qəbul edilmir . Onlar bir nümunə və ya sinifdən çağırmaq istisna olmaqla, sadə funksiyalar kimi davranırlar:

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

Staticmethods bir sinif sinfi ilə bəzi məntiqi əlaqə olan funksiyaları qruplaşdırmaq üçün istifadə olunur.


foo yalnız bir funksiyadır, ancaq a.foo , funksiyanı ala bilməyəcəksiniz, funksiyaya aid ilk dəlil kimi bağlanan obyektin a nümunəsi ilə funksiyanı "qismən tətbiq" versiyasını alırsınız. foo 2 arqument gözləyir və a.foo yalnız 1 arqument gözləyir.

a foo bağlıdır. "Bağlı" sözü aşağıdakılardır:

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

a.class_foo , a a.class_foo ilə a.class_foo deyil və sinif a class_foo ilə class_foo .

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

Burada staticmethod istifadə edərək, bu bir metod olmasına baxmayaraq, a.static_foo sadəcə heç bir bağlayıcı arqumenti olmayan yaxşı bir ole funksiyasını qaytarır. static_foo 1 arqumenti gözləyir və a.static_foo da 1 arqument gözləyir.

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

Və, əlbəttə ki, static_foo class a ilə çağırdığınızda eyni şey olur.

 print(a.static_foo) # <function static_foo at 0xb7d479cc> 
2560
03 нояб. Cavab verildi 03 noyabr. 2009-11-03 22:13 '09 at 10:13 pm 2009-11-03 22:13

Statik metod, onun adlandığı sinif və ya nümunə barədə heç bir məlumatı olmayan bir metoddur. Bu sadəcə qəbul edilmiş dəlilləri qəbul edir, ilk arqumenti nəzərdə tutmur. Bu, Python-da yararsızdır - staticmethodun yerinə modul funksiyasından istifadə edə bilərsiniz.

Digər tərəfdən, sinif metodu, ilk arqument kimi, çağrıldığı keçmiş sinfi və ya çağırılan nümunənin sinifini alan metoddur. Bu üsulun bir sinif üçün fabrik olmasını istəyirsinizsə, bu faydalıdır: ilk arqument kimi adlandırılan əsl sinifə sahib olduğundan, alt siniflərin iştirak etdiyi hallarda da doğru sinifin bir nümunəsini yarada bilərsiniz. Məsələn, dict.fromkeys() , classmethod, bir alt sinifdə çağırıldığında bir alt sinif nümunəsini necə qaytarır:

border=0
 >>> class DictSubclass(dict): ... def __repr__(self): ... return "DictSubclass" ... >>> dict.fromkeys("abc") {'a': None, 'c': None, 'b': None} >>> DictSubclass.fromkeys("abc") DictSubclass >>> 
708
26 сент. Thomas Wouters tərəfindən verilmiş cavab 26 Sep 2008-09-26 00:05 '08 də 0:05 2008-09-26 00:05

Əsasən, @classmethod ilk arqumentini çağırdığınız sinifdir (sinifin bir nümunəsi deyil) @staticmethod örtülü bir əsas yoxdur.

122
26 сент. Terence Simpson tərəfindən verilən cavab 26 sentyabr. 2008-09-26 00:07 '08 at 0:07 2008-09-26 00:07

Rəsmi python sənədləri:

@classmethod

Bir sinif metodu bir metodun bir nümunəsi olduğu kimi, sinfi bir örtük ilk arqument kimi qəbul edir. Bir sinif metodu elan etmək üçün bu deyimi istifadə edin:

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

@classmethod formu bir dekorativ funksiyasıdır - Tanımlama funksiyasındakı funksiya tərifinin təsvirinə baxın.

Bu, ya bir sinifdə (məsələn, Cf() ) və ya bir nümunədə (məsələn, C().f() ) deyilə bilər. Bir nümunə, onun sinfi istisna olmaqla, nəzərə alınmır. Sinif metodu türetilmiş bir sinif üçün çağırılırsa, türetilmiş sinifin məqsədi nəzərdə tutulan ilk arqumentdir.

Class üsulları C ++ və ya Java statik metodlarından fərqlidir. İstəsəniz, bu bölmədə staticmethod() baxın.

@ staticmethod

Statik metod örtük ilk arqument əldə etmir. Statik bir üsul elan etmək üçün bu deyimi istifadə edin:

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

@staticmethod forması bir dekorativ funksiyasıdır - Tanımlama funksiyasındakı funksiya təsvirinin təsvirinə baxın.

Bu, ya bir sinifdə (məsələn, Cf() ) və ya bir nümunədə (məsələn, C().f() ) deyilə bilər. Bir nümunə, onun sinfi istisna olmaqla, nəzərə alınmır.

Pythondakı statik metodlar Java və ya C ++-da olanlara bənzəyir. Daha inkişaf etmiş bir konsepsiya üçün, bu bölmədə classmethod() baxın.

82
03 нояб. Chris B tərəfindən 03 noyabr. 2009-11-03 22:23 '09 at 10:23 AM 2009-11-03 22:23

Bu mövzuda qısa bir məqalə var.

@ Stacymethod funksiyası bir sinifdə müəyyən edilmiş bir funksiyadan daha çox şeydir. Sınıfın bir örneğini yaratmadan çağırılabilir. Onun təsviri miras yoluyla dəyişilməzdir.

@Classmethod funksiyası sinifin nümunəsini yaratmadan da çağırıla bilər, ancaq onun təsviri ana sinifdən deyil, miras yolu ilə aparılır. Çünki @classmethod funksiyasına dair ilk arqument həmişə cls olmalıdır (sinif).

62
03 нояб. Cavab Tom Neyland tərəfindən verildi 03 noyabr. 2009-11-03 22:02 '09 at 10:02 AM 2009-11-03 22:02

@Staticmethod və ya @classmethod istifadə etmək qərarına gəlmək üçün, metodunuza baxmaq lazımdır. Metodunuz sinifinizdə digər dəyişənlərə / üsullara daxil olarsa, @classmethod istifadə edin . Digər tərəfdən, əgər metodunuz sinifin digər hissələrinə aid deyilsə, @staticmethod istifadə edin.

 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 
52
22 апр. Cavab D Du tərəfindən verilir. Apr 22 2016-04-22 18:40 '16 'da saat 18:40' da 2016-04-22 18:40

Python-da @staticmethod və @classmethod arasında fərq nədir?

Python kodu, bu pseudocode kimi müxtəlif metodların imzalarını nümayiş etdirən və hər birini izah etmək üçün bir vasitə təmin edən bir kodunu görmüş ola bilərsiniz:

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

Normal nümunə metodu

Əvvəlcə a_normal_instance_method izah a_normal_instance_method . Bu , nümunə metodu deyilir. Bir nümunə metodu istifadə edildikdə, istifadə edildikdə, arqumentlərin birincisi bütün xüsusiyyətləri olan bir nümunə obyekti olaraq əvvəlcədən təyin edilmiş qismən bir funksiya kimi istifadə olunur (hər bir mənbə üçün hər hansı bir dəyər üçün müəyyən edilən ümumi funksiyadan fərqli olaraq). Bununla əlaqəli bir obyektin bir nümunəsi var və bir obyektin nümunəsindən çağırılmalıdır. Bir qayda olaraq, bu nümunənin müxtəlif xüsusiyyətlərinə aiddir.

Məsələn, bu simli bir nümunəsidir:

 ', ' 

nümunə metodunu başqa bir iterable qoşulmaq üçün bu xəttə join istifadə edərsəniz, bu təkrarlanan funksiya funksiyasından başqa ['a', 'b', 'c'] funksiyası başqa bir nümunə funksiyasıdır:

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

Əlaqədar üsullar

Nümunə üsulları daha sonra istifadə üçün nöqtəli axtarış vasitəsi ilə əlaqələndirilə bilər.

Məsələn, str.join metodu ':' str.join bağlanır:

 >>> join_with_colons = ':'.join 

Və bundan sonra biz bununla bağlı olan ilk mübahisəyə malik bir funksiya kimi istifadə edə bilərik. Beləliklə, nümunənin qismən funksiyası kimi işləyir:

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

Statik metod

Statik metod bir dəlil kimi bir nümunəni qəbul etmir.

Modul səviyyəsi funksiyasına çox oxşardır.

Bununla birlikdə, modul səviyyəli funksiya modulda yaşamalı və xüsusilə istifadə olunduğu digər yerlərə idxal edilməlidir.

Bir obyektə əlavə edildikdə, həm də idxal və miras yoluyla obyektin içində hərəkət etmək rahatdır.

Statik metodun nümunəsi str.maketrans , string moduldan Python 3-ə köçürülür. Tərcümə cədvəlini str.translate istehlakı üçün str.translate . Aşağıda göstərildiyi kimi, simli nümunədən istifadə edildikdə, bu çox silly görünür, lakin string moduldan bir funksiyanı idxal etmək olduqca çətin və onu str.maketrans kimi sinifdən 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-də, bu funksiyanı getdikcə daha az faydalı bir simli moduldan idxal etməliyik:

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

Sinif metodu

Bir sinif metodu, nümunə metoduna bənzəyir, çünki bir örtük ilk arqumenti qəbul edir, lakin bir nümunəni qəbul etmək yerinə bir sinif qəbul edir. Çox vaxt semantik istifadə üçün alternativ konstruktorlar kimi istifadə olunurlar və mirasçılığı dəstəkləyəcəklər.

Daxili sinifin ən canonical nümunəsi dict.fromkeys . Alternativ diksiya konstruktoru kimi istifadə olunur (sizin nə olduğunuzu bildiyiniz zaman yaxşıdır və onlar üçün default olanı istəyirəm).

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

Biz subclass dict zaman, biz alt sinif bir nümunə yaradan eyni qurucusu istifadə edə bilərsiniz.

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

Alternativ konstruktorların digər oxşar nümunələri, eləcə də classmethodstaticmethod üzrə rəsmi Python sənədləri üçün pandas mənbə classmethod staticmethod .

40
23 янв. Cavab 23 yanvarda Aaron Hall tərəfindən verildi . 2015-01-23 23:01 '15 at 11:01 pm 2015-01-23 23:01

Python 2.4'də @decorators əlavə edildi. Python <2.4 istifadə edirsinizsə, classmethod () və staticmethod () funksiyalarını istifadə edə bilərsiniz.

Məsələn, bir fabrika metodu yaratmaq istəyirsinizsə (hansı argümanı götürdüyünə bağlı olaraq başqa bir sinif tətbiqinin bir nümunəsini qaytaran bir funksiya) belə bir şey edə bilərsiniz:

 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) 

Bundan əlavə, bu, sinfi metodu və statik metoddan istifadə etmək üçün yaxşı bir nümunədir. Statik metod açıqca sinifə aiddir, çünki o, klass klasterini istifadə edir. Sınıf yalnız bir obyektin nümunəsi deyil, sinif haqqında məlumat tələb edir.

_is_cluster_for classmethod metodunun yaradılmasının bir üstünlüyü subclass onun tətbiqini dəyişdirməyə qərar verə bilər, bəlkə də olduqca yayılmışdır və bir neçə klaster növünü idarə edə biləcəyi üçün, belə ki, yalnız sinif adını yoxlamaq kifayət deyil.

28
24 февр. 24 Fevralda Jens Timmerman tərəfindən verilmiş cavab. 2012-02-24 12:32 '12 at 12:32 2012-02-24 12:32

Ən yaxşı sual: "@classmethod və @staticmethod zaman istifadə edəcəksiniz?"

@classmethod asanlıqla sinif tərifi ilə əlaqəli olan xüsusi üzvlərə daxil olmaq imkanı verir. Bu yaradılmış obyektlərin nümunələrinin sayını nəzarət edən tək və ya fabrika sinifləri etmək üçün böyük bir yoldur.

@ staticmethod marginal performans qazanımı təmin edir, amma hələ də sinfi xaricində muxtar funksiya kimi icra edilə bilməyən bir sinif daxilində statik metoddan məhsuldar istifadəni görmək lazımdır.

27
19 мая '15 в 18:27 2015-05-19 18:27 Cavab Nathan Tregillus tərəfindən verilir 19 may, '15 saat 18:27 2015-05-19 18:27

Statik metodlar:

  • Arxivsiz sadə funksiyalar.
  • Sinif xüsusiyyətləri üzərində iş; nümunə atributları deyil.
  • Siz sinif və nümunə vasitəsilə müraciət edə bilərsiniz.
  • Onları yaratmaq üçün daxili staticmethod () funksiyası istifadə olunur.

Statik metodların üstünlükləri:

  • Bu funksiyanı adını classscope üçün lokallaşdırır.
  • Funksiya kodunu istifadə edilən yerə yaxınlaşdırır.
  • Modul səviyyəsində funksiyaları idxal etmək daha rahatdır, çünki hər bir metodun spesifik olaraq idxal edilməsinə ehtiyac yoxdur

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

Class üsulları:

  • Sınıf adı kimi ilk arqumenti olan funksiyalar.
  • Siz sinif və nümunə vasitəsilə müraciət edə bilərsiniz.
  • Daxili sinif metodu funksiyası ilə yaradılmışdır.

      @classmethod def some_class_method(cls, *args, **kwds): pass 
26
03 окт. Cavab Laxmi Oct 03. 2016-10-03 13:41 '16 saat 13:41 'də 2016-10-03 13:41

@staticmethod sadəcə bir funksiya funksiyası kimi default funksiyasını aradan qaldırır. Sınıf metodu, funksiyanı ilk arqument kimi öz sinifinə istinad edir ki, bir konteynerdə işlədir:

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

Əslində, classmethod iş müddəti ərzində xidmət məlumatları var, lakin sahibi sinifinə giriş imkanı verir. Alternativ olaraq, metaclass istifadə edərək, sinif metodlarını bu metaclass üzərinə qoymaq məsləhətdir:

 >>> class CMeta(type): ... def foo(cls): ... print cls ... >>> class C(object): ... __metaclass__ = CMeta ... >>> C.foo() <class '__main__.C'> 
21
26 сент. Cavab Armin Ronacher tərəfindən verilir 26 sep . 2008-09-26 00:24 '08 at 0:24 2008-09-26 00:24

Python-da statik, sərin və ya abstrakt metodlardan istifadə etmək üçün son təlimat bu mövzu üçün yaxşı əlaqələrdən biridir və onları aşağıdakılara azaldır.

@staticmethod funksiyası bir sinifdə müəyyən edilmiş bir funksiyadan daha çox şeydir. Sınıfın bir örneğini yaratmadan çağırılabilir. Onun təsviri miras yoluyla dəyişilməzdir.

  • Python, bir obyekt üçün bir bağlı metodu dərhal etməməlidir.
  • Bu, kodu oxunaqlılığını asanlaşdırır və obyektin vəziyyətindən asılı deyil;

@classmethod funksiyası bir sinifin dərhal edilməməsi @classmethod ola bilər, ancaq onun təsviri sub subclassı izləyir və miras vasitəsilə ana sinfi deyil, alt sinif tərəfindən yenidən təyin edilə bilər. Çünki @classmethod funksiyasına dair ilk arqument həmişə cls @classmethod (sinif).

  • Məsələn, bir sıra preprocessing istifadə edən bir sinif üçün bir nümunə yaratmaq üçün istifadə olunan zavod üsulları.
  • Statik metodları adlandırdığınız statik metodlar: statik metodları bir neçə statik metodlarla sındırarsanız, sinif adını hard-code etməlisiniz, lakin sinif metodlarından istifadə etməliyəm
18
16 нояб. Cavab 16 noyabrda zangw verilir. 2015-11-16 05:00 '15, 5:00 'də, 2015-11-16 05:00

C ++ ilə proqramlaşdırma dilini öyrənməyə başladım, daha sonra Java ilə, sonra da Python ilə, və hər birinin sadə istifadəini başa düşdüyümə qədər bu məsələ də məni narahat etdi.

Class üsulu: Python, Java və C ++-dan fərqli olaraq, heç bir konstruktor yüklənməmişdir. Və buna görə də, bu nail olmaq üçün, classmethod istifadə edə bilərsiniz. Aşağıdakı misal bunu izah edəcəkdir.

İki arqument, first_namelast_name alır və last_name nümunəsini yaradan bir şəxs last_name .

 class Person(object): def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name 

Əgər tələb yalnız bir ad istifadə edərək, bir sinif yaratmaq lazım olduğu halda, yalnız first_name , first_name belə bir şey edə bilməzsiniz .

Bir obyekt (nümunə) yaratmağa çalışdığınızda bu sizə bir səhv verəcəkdir.

 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 

Bununla belə, @classmethod aşağıdakı kimi istifadə edə bilərsiniz.

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

Statik metod: Bu olduqca sadədir, bir nümunəyə və ya sinifə bağlı deyil və sadəcə sinif adını istifadə edərək onu zəng edə bilərsiniz.

Beləliklə, məsələn, yuxarıda göstərilən misalda, first_name 20 simvoldan artıq olmamalı olduğunu təsdiqləməlisiniz, yalnız bunu edə bilərsiniz.

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

yalnız sinif adından istifadə edə bilərsiniz

 Person.validate_name("Gaurang Shah") 
17
10 окт. Cavab Gaurang Shah 10 oktyabr 2017-10-10 13:10 '17 saat 13:10 'da 2017-10-10 13:10

@classmethod deməkdir : bu metodu çağırarkən, sinfi bu sinifin bir nümunəsi əvəzinə ilk arqument kimi qəbul edirik (adətən üsullarla işləyirik). Bu, özünəməxsus bir nümunə deyil, bu metod daxilində sinfi və xüsusiyyətlərini istifadə edə bilərsiniz.

@ staticmethod deməkdir: bu üsul çağrıldığı zaman, biz bunu sinfi bir nümunə vermirik (adətən metodlarla olduğu kimi). Bu, bir sinif içərisində bir funksiya qoymaq deməkdir, ancaq bu sinifin bir nümunəsinə daxil ola bilməzsiniz (bu metodunuz bir nümunəni istifadə etmədikdə faydalıdır).

16
13 дек. Cavab 13 dekabrda Tushar.PUCSD tərəfindən verilir . 2015-12-13 22:37 '15 saat 10:37 'da, 2015-12-13 22:37

Staticmethod vs classmethod metoduna dair başqa bir nəzəriyyə miras ilə əlaqələndirilir. Deyək, aşağıdakı sinif var:

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

Və sonra uşaq sinifində bar() ləğv etmək istəyirsən:

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

Bu çalışır, lakin indi uşaq sinfində ( Foo2 ) bar() tətbiqinin artıq bu sinif üçün xüsusi bir şey istifadə edə bilməyəcəyini qeyd edin. Məsələn, Foo2 -də Foo2 bar() tətbiqində istifadə etmək istədiyiniz bir magic() metodu var:

 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" 

Burada Foo2.magic() çağırmaq Foo2.magic() , lakin sonra təkrar edirsiniz ( Foo2 adı Foo2 , bu metod bar() yadda saxlamağınız lazımdır).

Mənim üçün bu, açıq / qapalı prinsipin kiçik bir pozulmasıdır, çünki Foo verilən qərar, törəmə sinifdə refactor ümumi kod qabiliyyətinə təsir göstərir (yəni, genişlənməyə daha az açıqdır). bar() bir classmethod , yaxşı olardı:

 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

10
29 сент. Cavab Adam Parkin tərəfindən 29 sentyabrda verilir. 2016-09-29 20:02 '16 at 20:02 2016-09-29 20:02

İlk dəfə @classmethod vs @ staticmethod ilə bəzədilmiş üsulun bənzərliyi barədə danışaq.

Bənzərliklər: Hər ikisi sinifin özü və yalnız bir sinifdə deyil, çağırılmalıdır. Beləliklə, hər ikisi bir mənada, sinif üsullarıdır.

Fərq: sinif metodu sinfi özünü ilk arqument kimi qəbul edəcək, lakin statik metod olmayacaq.

Beləliklə, statik metod, bir mənada, sinfi özü ilə əlaqəli deyil və sadəcə funksionallıqla əlaqəli ola biləcəyindən asılıdır.

 >>> 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',) 
10
14 янв. Cavab 14 yanvarda Selva tərəfindən verilir . '18 в 17:07 2018-01-14 17:07

Я попытаюсь объяснить основное различие с помощью примера.

 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 Ax # 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 - мы можем напрямую вызвать static и classmethods без инициализации

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

2- Статический метод не может вызвать метод self, но может вызывать другие статические и classmethod

3 Статический метод принадлежит классу и вообще не будет использовать объект.

Метод класса не связан с объектом, а с классом.

8
ответ дан Rizwan Mumtaz 20 сент. '16 в 12:03 2016-09-20 12:03

В Python метод class получает класс как неявный первый аргумент. Класс экземпляра объекта неявно передается как первый аргумент. Это может быть полезно когда требуется, чтобы этот метод был factory класса, поскольку он получает фактический класс (который называется методом) в качестве первого аргумента, можно создать экземпляр правого класса, даже если также рассматриваются подклассы.

Статический метод - это просто функция, определенная внутри класса. Он ничего не знает о классе или экземпляре, на который он был вызван, и получает только аргументы, которые были переданы без какого-либо неявного первого аргумента. Məsələn:

 class Test(object): def foo(self, a): print "testing (%s,%s)"%(self,a) @classmethod def foo_classmethod(cls, a): print "testing foo_classmethod(%s,%s)"%(cls,a) @staticmethod def foo_staticmethod(a): print "testing foo_staticmethod(%s)"%a test = Test() 

staticmethods используются для группировки функций, которые имеют некоторое логическое соединение с классом в классе.

6
ответ дан Green Harry 06 июля '16 в 11:53 2016-07-06 11:53

@classmethod: может использоваться для создания общего глобального доступа ко всем экземплярам, ​​созданным в этом классе... например, для обновления записи несколькими пользователями... Я особенно нашел, что он полезен при создании синглетонов.:)

@статический метод: не имеет никакого отношения к классу или экземпляру, связанному с... но для удобства чтения можно использовать статический метод

4
ответ дан vijay 20 сент. '17 в 19:57 2017-09-20 19:57

метод класса vs статический метод в Python

Метод класса

Декоратор @classmethod - встроенный декоратор функций, который является выражением, которое оценивается после определения вашей функции. Результат этой оценки затеняет ваше определение функции.

Метод класса получает класс как неявный первый аргумент, так же как метод экземпляра получает экземпляр

Синтаксис:

 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. 
  • Метод класса - это метод, связанный с классом, а не с объектом класса.
  • Они имеют доступ к состоянию класса, поскольку он принимает параметр класса, который указывает на класс, а не на экземпляр объекта.
  • Он может изменять состояние класса, которое будет применяться во всех экземплярах класса. Например, он может модифицировать переменную класса, которая будет применима ко всем экземплярам.

Статический метод

Статический метод не получает неявный первый аргумент.

Синтаксис:

 class C(object): @staticmethod def fun(arg1, arg2, ...): ... returns: a static method for function fun. 
  • Статический метод также является методом, который связан с классом, а не с объектом класса.
  • Статический метод не может получить доступ или изменить состояние класса.
  • Он присутствует в классе, потому что имеет смысл, чтобы метод присутствовал в классе.

Метод класса против статического метода

  • Метод класса принимает cls как первый параметр, тогда как статический метод не нуждается в конкретных параметрах.
  • Метод класса может получить доступ или изменить состояние класса, когда статический метод не может получить доступ или изменить его.
  • Мы используем @classmethod decorator в python для создания метода класса, и мы используем @staticmethod decorator для создания статического метода в python.

Когда использовать что?

  • Обычно мы используем метод класса для создания заводских методов. Фабричные методы возвращают объект класса (похожий на конструктор) для разных вариантов использования.
  • Обычно мы используем статические методы для создания служебных функций.

Как определить метод класса и статический метод?

Чтобы определить метод класса в python, мы используем декоратор @classmethod и определяем статический метод, которым мы используем декоратор @staticmethod.

Давайте посмотрим на пример, чтобы понять разницу между ними. Скажем, мы хотим создать класс Person. Теперь python не поддерживает перегрузку метода, например C++ или Java, поэтому мы используем методы класса для создания заводских методов. В приведенном ниже примере мы используем метод класса для создания объекта person из года рождения.

Как объяснялось выше, мы используем статические методы для создания служебных функций. В приведенном ниже примере мы используем статический метод для проверки того, является ли человек взрослым или нет.

Реализация

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

Вывод

 21 21 True 

Kömək edin

3
ответ дан chirag maliwal 22 янв. '18 в 23:11 2018-01-22 23:11

Мой вклад демонстрирует разницу между @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 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) ''' """ 
2
ответ дан Michael Swartz 25 июня '18 в 5:38 2018-06-25 05:38

Методы класса, как следует из названия, используются для внесения изменений в классы, а не в объекты. Чтобы внести изменения в классы, они будут изменять атрибуты класса (а не атрибуты объекта), поскольку именно так вы обновляете классы. Именно по этой причине методы класса берут класс (условно обозначаемый "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. Eg Some global variable/function." 
1
ответ дан Tushar Vazirani 01 дек. '17 в 13:38 2017-12-01 13:38

Анализ @staticmethod буквально предоставляет разные идеи.

Обычный метод класса - это неявный динамический метод, который принимает экземпляр как первый аргумент.
Напротив, staticmethod не принимает экземпляр в качестве первого аргумента, поэтому он называется "static" .

Статический метод действительно является такой нормальной функцией, как те, которые находятся вне определения класса.
Он, к счастью, сгруппирован в класс только для того, чтобы стоять ближе, где он применяется, или вы можете прокручивать его, чтобы найти его.

1
ответ дан JawSaw 12 дек. '17 в 12:40 2017-12-12 12:40

Вы можете рассмотреть разницу между:

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

Это изменилось между python2 и python3:

python2:

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

Поэтому использование @staticmethod для методов, вызываемых только непосредственно из класса, стало необязательным в python3. Если вы хотите вызывать их как из класса, так и из экземпляра, вам все равно нужно использовать декоратор @staticmethod .

Остальные случаи были хорошо охвачены ответом unutbus.

0
ответ дан David Nathan 24 янв. '19 в 15:56 2019-01-24 15:56
 #!/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() 
-4
ответ дан Zuckonit 18 нояб. '13 в 8:53 2013-11-18 08:53

Быстрое взлома одних и тех же методов в iPython показывает, что @staticmethod дает предельный прирост производительности (в наносекундах), но в остальном он, похоже, не функционирует. Кроме того, любые улучшения производительности, вероятно, будут уничтожены дополнительной работой по обработке метода с помощью staticmethod() во время компиляции (что происходит до выполнения любого кода при запуске script).

Для удобства чтения кода я бы избегал @staticmethod , если ваш метод не будет использоваться для нагрузок работы, где подсчитываются наносекунды.

-5
ответ дан Cathal Garvey 17 дек. '12 в 21:51 2012-12-17 21:51

Другие вопросы по меткам или Задайте вопрос