@Staticmethod ve @classmethod aras─▒ndaki fark nedir?


Al─▒nan cevaba git


Bir fonksiyonu s├╝slenmi┼č aras─▒ndaki fark nedir @staticmethod ve bir dekore @classmethod ?


3303









Cevap say─▒s─▒n─▒ say: 23






├ça─čr─▒ imzalar─▒ fark fark─▒n─▒: Belki ├Ârnek kod biraz yard─▒mc─▒ olacakt─▒r foo , class_foo ve 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─č─▒da, bir nesne ├Ârne─činin bir y├Ântem ├ža─č─▒rd─▒─č─▒ normal y├Ântemdir. Nesne ├Ârne─či, a ilk arg├╝man olarak ├Ârt├╝k olarak iletilir.

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

Classmethods ile , nesne ├Ârne─činin s─▒n─▒f─▒ ├Ârt├╝l├╝ olarak, yerine ilk arg├╝man olarak ge├žirilir self .

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

class_foo S─▒n─▒f─▒ kullanarak da arayabilirsiniz . Asl─▒nda, bir s─▒n─▒f metodu olacak bir ┼čey tan─▒mlarsan─▒z, bunun nedeni muhtemelen onu bir s─▒n─▒f ├Ârne─činden ziyade s─▒n─▒ftan ├ža─č─▒rmak istedi─činizdir. A.foo(1) bir TypeError y├╝kseltecekti, ancak A.class_foo(1) gayet iyi ├žal─▒┼č─▒yor:

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

─░nsanlar─▒n s─▒n─▒f y├Ântemleri i├žin bulduklar─▒ bir kullan─▒m, kal─▒tsal alternatif kurucular yaratmakt─▒r .


Statik y├Ântemlerle ne self (nesne ├Ârne─či) ne de cls (s─▒n─▒f) ilk arg├╝man olarak ├Ârt├╝k olarak ge├žirilmez. Bunlar─▒ bir ├Ârnek veya s─▒n─▒ftan ├ža─č─▒rabilece─činiz durumlar d─▒┼č─▒nda d├╝z i┼člevler gibi davran─▒rlar:

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

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

Statik metotlar, s─▒n─▒fa s─▒n─▒fla mant─▒ksal ba─člant─▒s─▒ olan fonksiyonlar─▒ gruplamak i├žin kullan─▒l─▒r.


foo sadece bir fonksiyondur, fakat ├ža─č─▒rd─▒─č─▒n─▒zda a.foo sadece fonksiyonu almazs─▒n─▒z, fonksiyonun a ilk arg├╝man─▒ olarak ba─čl─▒ olan nesne ├Ârne─či ile fonksiyonun "k─▒smen uygulanm─▒┼č" versiyonunu al─▒rs─▒n─▒z . foo 2 arg├╝man beklerken, a.foo sadece 1 arg├╝man beklenir .

a ba─čl─▒ foo . A┼ča─č─▒daki "ba─čl─▒" terimi ile kastedilen budur:

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

─░le a.class_foo , a ba─čl─▒ class_foo de─čil, s─▒n─▒f A ba─čl─▒ class_foo .

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

Burada, statik bir y├Ântemle, bir y├Ântem olmas─▒na ra─čmen, a.static_foo hi├žbir arg├╝man ba─čl─▒ olmadan iyi bir 'ole' i┼člevi d├Ând├╝r├╝r. static_foo 1 arg├╝man─▒ a.static_foo bekler ve 1 arg├╝man─▒ da bekler.

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

Ve elbette ayn─▒ ┼čey static_foo s─▒n─▒fla birlikte arad─▒─č─▒n─▒zda da oluyor A .

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

2911







Bir duruky├Ântem ├ťzerinde denilen s─▒n─▒f veya ├Ârne─či hakk─▒nda hi├žbir ┼čey bilmeyen bir y├Ântemdir. Sadece iletilen arg├╝manlar─▒ al─▒r, ├Ârt├╝k bir ilk arg├╝man yoktur. Python'da temel olarak i┼če yaramaz - statik bir metot yerine sadece bir mod├╝l fonksiyonunu kullanabilirsiniz.

Bir classmethod , di─čer taraftan, birinci ba─č─▒ms─▒z de─či┼čken olarak, bu ilgili denilen s─▒n─▒f─▒ ya da ├╝zerinde denilen ├Ârne─činin s─▒n─▒f─▒ ge├žirilen bir y├Ântemdir. Y├Ântemin s─▒n─▒f i├žin bir fabrika olmas─▒n─▒ istedi─činizde kullan─▒┼čl─▒d─▒r: ilk arg├╝man olarak adland─▒r─▒lan as─▒l s─▒n─▒f─▒ ald─▒─č─▒ndan, alt s─▒n─▒flar dahil olsa bile, her zaman do─čru s─▒n─▒f─▒ ba┼člatabilirsiniz. ├ľrne─čin dict.fromkeys() , bir s─▒n─▒f y├Ânteminin bir alt s─▒n─▒fta ├ža─čr─▒ld─▒─č─▒nda alt s─▒n─▒f─▒n bir ├Ârne─čini nas─▒l d├Ând├╝rd├╝─č├╝n├╝ g├Âzlemleyin :

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

759







Temel olarak @classmethod , ilk arg├╝man─▒ ├ža─čr─▒ld─▒─č─▒ s─▒n─▒f olan (s─▒n─▒f ├Ârne─či yerine), @staticmethod herhangi bir ├Ârt├╝l├╝ arg├╝man i├žermeyen bir y├Ântem yapar .


136







Resmi piton belgeleri:

@classmethod

Bir s─▒n─▒f y├Ântemi, s─▒n─▒f─▒ bir ├Ârnek y├Ânteminin ald─▒─č─▒ gibi, dolayl─▒ olarak ilk arg├╝man olarak al─▒r. Bir s─▒n─▒f y├Ântemi bildirmek i├žin bu deyimi kullan─▒n:

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

@classmethod Form bir i┼člevdir dekorat├Âr - fonksiyonu tan─▒mlar─▒n a├ž─▒klamas─▒na bak─▒n Fonksiyon tan─▒mlar─▒ ayr─▒nt─▒lar i├žin.

S─▒n─▒fta (├Ârne─čin C.f() ) veya bir ├Ârnekte (├Ârne─čin) ├ža─čr─▒labilir C().f() . ├ľrnek, s─▒n─▒f─▒ d─▒┼č─▒nda dikkate al─▒nmaz. T├╝retilmi┼č bir s─▒n─▒f i├žin bir s─▒n─▒f y├Ântemi ├ža─čr─▒l─▒rsa, t├╝retilmi┼č s─▒n─▒f nesnesi z─▒mni ilk arg├╝man olarak iletilir.

S─▒n─▒f y├Ântemleri, C ++ veya Java statik y├Ântemlerinden farkl─▒d─▒r. Bunlar─▒ istiyorsan─▒z, staticmethod() bu b├Âl├╝me bak─▒n.

@staticmethod

Statik bir y├Ântem, ├Ârt├╝k bir birinci arg├╝man almaz. Statik bir y├Ântem bildirmek i├žin bu deyimi kullan─▒n:

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

@staticmethod Form bir i┼člevdir dekorat├Âr - fonksiyonu tan─▒mlar─▒n a├ž─▒klamas─▒na bak─▒n Fonksiyon tan─▒mlar─▒ ayr─▒nt─▒lar i├žin.

S─▒n─▒fta (├Ârne─čin C.f() ) veya bir ├Ârnekte (├Ârne─čin) ├ža─čr─▒labilir C().f() . ├ľrnek, s─▒n─▒f─▒ d─▒┼č─▒nda dikkate al─▒nmaz.

Python'daki statik y├Ântemler Java veya C ++ 'da bulunanlara benzer. Daha geli┼čmi┼č bir konsept classmethod() i├žin bu b├Âl├╝me bak─▒n─▒z.


97







─░┼čte bu soru ├╝zerine k─▒sa bir makale

@staticmethod i┼člevi, bir s─▒n─▒f i├žinde tan─▒mlanan bir i┼člevden ba┼čka bir ┼čey de─čildir. ├ľnce s─▒n─▒fa ba┼člamadan ├ža─čr─▒labilir. Tan─▒m─▒ miras yoluyla de─či┼čmez.

@classmethod i┼člevi ayr─▒ca, s─▒n─▒f─▒ ba┼člatmadan ├ža─čr─▒labilir, ancak tan─▒m─▒, Kal─▒t─▒m yoluyla ├ťst s─▒n─▒f─▒ de─čil, Alt s─▒n─▒f─▒ izler. ├ç├╝nk├╝ classmethod i┼člevi i├žin ilk arg├╝man her zaman cls (class) olmal─▒d─▒r.


70







@Staticmethod veya @classmethod kullan─▒p kullanmamaya karar vermek i├žin y├Ânteminizin i├žine bakmak gerekir. Y├Ânteminiz s─▒n─▒f─▒n─▒zdaki di─čer de─či┼čkenlere / y├Ântemlere eri┼čiyorsa, @classmethod ├Â─česini kullan─▒n . ├ľte yandan, y├Ânteminiz s─▒n─▒f─▒n di─čer b├Âl├╝mlerine dokunmuyorsa @staticmethod kullan─▒n.

 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
 

59







Python'da @staticmethod ve @classmethod aras─▒ndaki fark nedir?

├çe┼čitli y├Ântem t├╝rlerinin imzalar─▒n─▒ g├Âsteren ve her birini a├ž─▒klamak i├žin bir dok├╝mantasyon sa─člayan bu sahte kod gibi Python kodunu g├Ârm├╝┼č olabilirsiniz:

 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 ├ľrnek Y├Ântemi

─░lk ├Ânce a├ž─▒klayaca─č─▒m a_normal_instance_method . Buna kesin olarak " ├Ârnek y├Ântem " denir . Bir ├Ârnek y├Ântemi kullan─▒ld─▒─č─▒nda, k─▒smi bir i┼člev olarak kullan─▒l─▒r (kaynak kodda g├Âr├╝nt├╝lendi─činde t├╝m de─čerler i├žin tan─▒mlanm─▒┼č bir toplam i┼člev yerine), yani kullan─▒ld─▒─č─▒nda arg├╝manlar─▒n ilki ├Ânceden tan─▒mlan─▒r. verilen t├╝m ├Âzniteliklere sahip nesne. Kendisine ba─čl─▒ nesnenin ├Ârne─čine sahiptir ve nesnenin bir ├Ârne─činden ├ža─čr─▒lmal─▒d─▒r. Genellikle, ├Ârne─čin ├že┼čitli ├Âzelliklerine eri┼čir.

├ľrne─čin, bu bir dize ├Ârne─čidir:

 ', '
 

join example y├Ântemini, bu dizgede, yinelenebilir ba┼čka bir ├Â─čeye kat─▒lmak i├žin kullan─▒rsak, yinelenebilir listenin bir i┼člevi olmas─▒n─▒n yan─▒ s─▒ra, ├Ârne─čin bir i┼člevi de a├ž─▒kt─▒r ['a', 'b', 'c'] :

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

S─▒n─▒r y├Ântemleri

├ľrnek y├Ântemleri daha sonra kullan─▒lmak ├╝zere noktal─▒ bir arama yoluyla ba─članabilir.

├ľrne─čin, bu ba─člar str.join i├žin bir y├Ântem ':' , ├Ârne─čin:

 >>> join_with_colons = ':'.join 
 

Ve daha sonra bunu zaten kendisine ba─čl─▒ olan ilk arg├╝mana sahip olan bir i┼člev olarak kullanabiliriz. Bu ┼čekilde, ├Ârnekte k─▒smi bir fonksiyon gibi ├žal─▒┼č─▒r:

 >>> 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 Y├Ântem

Statik y├Ântem yok de─čil bir arg├╝man olarak ├Ârne─čini almak.

Bir mod├╝l seviye fonksiyonuna ├žok benzer.

Bununla birlikte, mod├╝l d├╝zeyinde bir i┼člev mod├╝lde ya┼čamal─▒ ve ├Âzel olarak kullan─▒ld─▒─č─▒ di─čer yerlere aktar─▒lmal─▒d─▒r.

Bununla birlikte, nesneye eklenmi┼čse, nesneyi i├že aktarma ve devralma yoluyla rahatl─▒kla izleyecektir.

Statik bir y├Ânteme ├Ârnek Python 3'teki mod├╝lden str.maketrans ta┼č─▒n─▒r . string T├╝ketim i├žin uygun bir ├ževiri tablosu yapar str.translate . A┼ča─č─▒da g├Âsterildi─či gibi bir dize ├Ârne─činden kullan─▒ld─▒─č─▒nda olduk├ža sa├žma g├Âr├╝nmektedir, ancak i┼člevi string mod├╝lden i├že aktarmak olduk├ža sakard─▒r ve onu s─▒n─▒ftan oldu─ču gibi s─▒n─▒ftan ├ža─č─▒rabilir 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'de, bu i┼člevi giderek daha az kullan─▒lan string mod├╝l├╝nden almak zorundas─▒n─▒z:

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

S─▒n─▒f y├Ântemi

Bir s─▒n─▒f y├Ântemi, ├Ârt├╝k bir ilk arg├╝man ald─▒─č─▒ bir ├Ârnek y├Ântemine benzer, ancak ├Ârne─či almak yerine s─▒n─▒f─▒ al─▒r. S─▒kl─▒kla bunlar daha iyi anlamsal kullan─▒m i├žin alternatif kurucu olarak kullan─▒l─▒rlar ve kal─▒t─▒msall─▒─č─▒ desteklerler.

Yerle┼čik bir s─▒n─▒f metodun en kanonik ├Ârne─či dict.fromkeys . Alternatif bir dict kurucusu olarak kullan─▒l─▒r, (anahtarlar─▒n─▒z─▒n ne oldu─čunu bildi─činiz ve onlar i├žin varsay─▒lan bir de─čer istedi─činiz zamanlar i├žin ├žok uygundur.)

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

Dict alt s─▒n─▒f─▒nda, alt s─▒n─▒f─▒n bir ├Ârne─čini yaratan ayn─▒ yap─▒c─▒y─▒ kullanabiliriz.

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

Bkz pandalar kaynak kodunu alternatif in┼čaat├ž─▒ di─čer benzer ├Ârnekler i├žin ve ayr─▒ca resmi Python belgelerine bak─▒n classmethod ve staticmethod .


48







Programlama dilini C ++ ve sonra Java ve Python ile ├Â─črenmeye ba┼člad─▒m ve her birinin basit kullan─▒m─▒n─▒ anlayana kadar bu soru beni ├žok rahats─▒z etti.

S─▒n─▒f Y├Ântemi: Java ve C ++ 'dan farkl─▒ olarak Python, yap─▒c─▒ a┼č─▒r─▒ y├╝klemesine sahip de─čil. Ve b├Âylece bunu ba┼čarmak i├žin kullanabilirsiniz classmethod . A┼ča─č─▒daki ├Ârnek bunu a├ž─▒klayacakt─▒r

Person ─░ki arg├╝man alan first_name ve last_name ├Ârne─čini yaratan bir s─▒n─▒f─▒m─▒z oldu─čunu d├╝┼č├╝nelim Person .

 class Person(object):

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

E─čer sadece bir, sadece tek bir ad kullanarak bir s─▒n─▒f olu┼čturmak i├žin gereken yere ┼×imdi, e─čer gereksinim geliyor first_name , sen olamaz Python b├Âyle bir ┼čey yapmak.

Bir nesne olu┼čturmaya ├žal─▒┼čt─▒─č─▒n─▒zda bu size bir hata verecektir (├Ârnek).

 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
 

Ancak, @classmethod a┼ča─č─▒da belirtilenleri kullanarak ayn─▒ ┼čeyi ba┼čarabilirsiniz

 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 Y├Ântem: Bu olduk├ža basittir, ├Ârnek veya s─▒n─▒fa ba─čl─▒ de─čildir ve bunu sadece s─▒n─▒f ad─▒n─▒ kullanarak ├ža─č─▒rabilirsiniz.

Diyelim ki yukar─▒daki ├Ârnekte first_name 20 karakteri ge├žmemesi gereken bir onaylamaya ihtiyac─▒n─▒z var , bunu basit├že yapabilirsiniz.

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

ve kullanarak arama yapabilirsiniz class name

 Person.validate_name("Gaurang Shah")
 

37







@decorators python 2.4 i├žine eklendi. python <2.4 kullan─▒yorsan─▒z, classmethod () ve staticmethod () i┼člevini kullanabilirsiniz.

├ľrne─čin, bir fabrika y├Ântemi olu┼čturmak istiyorsan─▒z (hangi arg├╝mana ba─čl─▒ oldu─čuna ba─čl─▒ olarak s─▒n─▒f─▒n farkl─▒ bir uygulamas─▒n─▒n ├Ârne─čini d├Ând├╝ren bir i┼člev) a┼ča─č─▒daki gibi bir ┼čey yapabilirsiniz:

 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)
 

Ayr─▒ca bunun bir s─▒n─▒f metodu ve statik bir y├Ântem kullanmak i├žin iyi bir ├Ârnek oldu─čunu g├Âzlemleyin, Statik y├Ântem a├ž─▒k├ža s─▒n─▒f─▒na aittir, ├ž├╝nk├╝ Cluster s─▒n─▒f─▒n─▒ dahili olarak kullan─▒r. Classmethod yaln─▒zca s─▒n─▒f hakk─▒nda bilgiye ihtiya├ž duyar ve nesnenin ├Ârne─čini almaz.

_is_cluster_for Y├Ântemi bir s─▒n─▒f metodu yapman─▒n ba┼čka bir yarar─▒, bir alt s─▒n─▒f─▒n uygulanmas─▒n─▒ de─či┼čtirmeye karar verebilmesidir, belki de olduk├ža genel oldu─čundan ve birden fazla k├╝me t├╝r├╝n├╝ i┼čleyebildi─činden, sadece s─▒n─▒f─▒n ad─▒n─▒ kontrol etmek yeterli olmaz.


30







Bence daha iyi bir soru "Ne zaman @classmethod vs @staticmethod kullan─▒rs─▒n─▒z?"

@classmethod, s─▒n─▒f tan─▒m─▒yla ili┼čkili ├Âzel ├╝yelere kolay eri┼čim sa─člar. Bu, singleton'lar─▒ yapmak veya yarat─▒lan nesnelerin ├Ârneklerinin say─▒s─▒n─▒ kontrol eden fabrika s─▒n─▒flar─▒n─▒ yapmak i├žin harika bir yoldur.

@staticmethod marjinal performans kazan─▒mlar─▒ sa─člar, ancak s─▒n─▒f d─▒┼č─▒nda ba─č─▒ms─▒z bir i┼člev olarak elde edilemeyen bir s─▒n─▒f i├žinde statik bir y├Ântemin verimli bir kullan─▒m─▒n─▒ g├Ârmedim.


29







Statik Y├Ântemler:

  • Kendini tart─▒┼čmadan basit fonksiyonlar.
  • S─▒n─▒f ├Âzellikleri ├╝zerinde ├žal─▒┼č─▒n; ├Ârnek niteliklerinde de─čil.
  • Hem s─▒n─▒f hem de ├Ârnek arac─▒l─▒─č─▒yla ├ža─čr─▒labilir.
  • Yerle┼čik i┼člevi staticmethod () bunlar─▒ olu┼čturmak i├žin kullan─▒l─▒r.

Statik Y├Ântemlerin Yararlar─▒:

  • Classscope i├žindeki fonksiyon ismini yerelle┼čtirir
  • ─░┼člev kodunu kullan─▒ld─▒─č─▒ yere yakla┼čt─▒r─▒r
  • Her seviye ├Âzel olarak i├že aktar─▒lmak zorunda olmad─▒─č─▒ndan, mod├╝l d├╝zeyinde i┼člevlere kar┼č─▒ i├že aktarma daha uygundur

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

S─▒n─▒f Y├Ântemleri:

  • S─▒n─▒f ismi olarak ilk arg├╝man olan fonksiyonlar.
  • Hem s─▒n─▒f hem de ├Ârnek arac─▒l─▒─č─▒yla ├ža─čr─▒labilir.
  • Bunlar, s─▒n─▒f i├ži yerle┼čik i┼člev ile olu┼čturulur.

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

27







@staticmethod sadece varsay─▒lan i┼člevi y├Ântem tan─▒mlay─▒c─▒ olarak devre d─▒┼č─▒ b─▒rak─▒r. classmethod, i┼člevinizi, sahip oldu─ču s─▒n─▒fa bir ba┼čvuru olarak ilk arg├╝man olarak ileten bir konteyner ├ža─čr─▒labilirine sarar:

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

Nitekim, classmethod bir ├žal─▒┼čma zaman─▒ ek y├╝k├╝ vard─▒r ancak sahip olma s─▒n─▒f─▒na eri┼čmeyi m├╝mk├╝n k─▒lar. Alternatif olarak, bir metaclass kullanman─▒z─▒ ve bu metaclass ├╝zerinde s─▒n─▒f y├Ântemlerini koyman─▒z─▒ ├Âneririm:

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

21







Python'da statik, s─▒n─▒f veya soyut y├Ântemlerin nas─▒l kullan─▒laca─č─▒na dair kesin rehber bu konu i├žin iyi bir ba─člant─▒d─▒r ve a┼ča─č─▒daki gibi ├Âzetleyin.

@staticmethod i┼člev, bir s─▒n─▒f i├žinde tan─▒mlanm─▒┼č bir i┼člevden ba┼čka bir ┼čey de─čildir. ├ľnce s─▒n─▒fa ba┼člamadan ├ža─čr─▒labilir. Tan─▒m─▒ miras yoluyla de─či┼čmez.

  • Python, nesne i├žin bir ba─čl─▒ y├Ântemi ba┼člatmak zorunda de─čildir.
  • Kodun okunabilirli─čini kolayla┼čt─▒r─▒r ve nesnenin durumuna ba─čl─▒ de─čildir;

@classmethod i┼člev ayn─▒ zamanda s─▒n─▒f─▒ ba┼člatmadan ├ža─čr─▒labilir, ancak tan─▒m─▒ Ana s─▒n─▒f─▒ de─čil miras yoluyla alt s─▒n─▒f─▒ ge├žersiz k─▒labilir. ├ç├╝nk├╝ @classmethod fonksiyon i├žin ilk arg├╝man daima cls (class) olmal─▒d─▒r.

  • ├ľrne─čin bir ├že┼čit ├Ân i┼čleme kullanarak bir s─▒n─▒f i├žin ├Ârnek olu┼čturmak i├žin kullan─▒lan fabrika y├Ântemleri .
  • Statik y├Ântemleri ├ža─č─▒ran statik y├Ântemler : statik y├Ântemleri ├že┼čitli statik y├Ântemlerde b├Âlerseniz, s─▒n─▒f ad─▒n─▒ zor kodlamaman─▒z ancak s─▒n─▒f y├Ântemlerini kullanman─▒z gerekir.

19







├ľnce @classmethod vs @staticmethod ile s├╝slenmi┼č bir y├Ântem aras─▒ndaki benzerli─či s├Âyleyeyim.

Benzerlik: Her ikisi de sadece s─▒n─▒f─▒n ├Ârne─či yerine S─▒n─▒f─▒n kendisinde ├ža─čr─▒labilir . Yani, her ikisi de bir anlamda S─▒n─▒f─▒n y├Ântemleridir .

Fark: Bir s─▒n─▒f metodu, s─▒n─▒f─▒n kendisini ilk arg├╝man olarak al─▒rken, bir statik metot almaz.

Dolay─▒s─▒yla, statik y├Ântem, bir anlamda, S─▒n─▒f─▒n kendisine ba─čl─▒ de─čildir ve sadece ilgili bir i┼člevselli─če sahip olabilece─či i├žin orada as─▒l─▒ kalmaktad─▒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',)
 

14







Statik metodu ve s─▒n─▒f metodu ile ilgili bir di─čer husus ise kal─▒t─▒mla ilgilidir. Diyelim ki a┼ča─č─▒daki s─▒n─▒fa sahipsiniz:

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

Ve sonra bar() bir ├žocuk s─▒n─▒f─▒nda ge├žersiz k─▒lmak istiyorsunuz :

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

Bu i┼če yarar, ancak art─▒k bar() ├žocuk s─▒n─▒f─▒ndaki ( Foo2 ) uygulaman─▒n o s─▒n─▒fa ├Âzg├╝ herhangi bir ┼čeyden art─▒k yararlanamayaca─č─▒n─▒ unutmay─▒n. ├ľrne─čin, diyelim ki uygulamas─▒nda kullanmak istedi─činiz Foo2 bir y├Ântem vard─▒ : 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" 
 

Ge├žici ├ž├Âz├╝m burada aramak olurdu Foo2.magic() i├žinde bar() ama (ad─▒n─▒ o zaman kendini tekrar ediyorsun Foo2 de─či┼čikliklerle, bunu g├╝ncellemek i├žin hat─▒rlamak gerekecek bar() y├Ântemi).

Bana g├Âre bu, a├ž─▒k / kapal─▒ prensibin hafif bir ihlalidir , ├ž├╝nk├╝ al─▒nan bir karar, Foo ortak bir kodu t├╝retilmi┼č bir s─▒n─▒fta yeniden kodlama yetene─činizi etkilemektedir (yani, uzant─▒ya daha az a├ž─▒kt─▒r). E─čer bar() bir vard─▒ classmethod biz iyi olurdu:

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

verir: In Foo2 MAGIC


12







Bir ├Ârnek kullanarak temel fark─▒ a├ž─▒klamaya ├žal─▒┼čaca─č─▒m.

 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 - ba┼člatmadan statik ve s─▒n─▒f metotlar─▒n─▒ do─črudan ├ža─č─▒rabiliriz.

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

2- Statik metot kendi kendine metodu arayamaz fakat di─čer statik ve s─▒n─▒f y├Ântemlerini arayabilir.

3- Statik y├Ântem s─▒n─▒fa aittir ve hi├žbir ┼čekilde nesne kullanmaz.

4- S─▒n─▒f y├Ântemi bir nesneye de─čil bir s─▒n─▒fa ba─član─▒r.


8







─░lk arg├╝man farkl─▒ :

  • normal y├Ântem: ilk arg├╝man (otomatik olarak) mevcut nesnedir
  • classmethod: first arg├╝man─▒ (otomatik olarak) mevcut nesnenin s─▒n─▒f─▒d─▒r
  • duruky├Ântem: ─░lk arg├╝man ge├žmedi otomatik

Daha detayl─▒ olarak ...

normal y├Ântem

Bir nesnenin y├Ântemi ├ža─čr─▒ld─▒─č─▒nda, otomatik self olarak ilk arg├╝man─▒ olarak ekstra bir arg├╝man verilir . Yani, y├Ântem

 def f(self, x, y)
 

2 arg├╝man ile ├ža─čr─▒lmal─▒d─▒r. self otomatik olarak ge├žirilir ve nesnenin kendisidir .

s─▒n─▒f y├Ântemi

Y├Ântem dekore edildi─činde

 @classmethod
def f(cls, x, y)
 

otomatik olarak verilen arg├╝man de─čil self , s─▒n─▒f─▒d─▒r self .

statik y├Ântem

Y├Ântem dekore edildi─činde

 @staticmethod
def f(x, y)
 

y├Ântem hi├žbir otomatik arg├╝man verilmez . Sadece onunla ├ža─čr─▒ld─▒─č─▒ parametreler verilir.

kullan─▒mlar─▒

  • classmethod ├žo─čunlukla alternatif in┼čaat├ž─▒lar i├žin kullan─▒l─▒r.
  • staticmethod nesnenin durumunu kullanmaz. Bir s─▒n─▒fa harici bir fonksiyon olabilir. Yaln─▒zca s─▒n─▒f─▒n i├žine benzer i┼člevleri olan i┼člevleri gruplamak i├žin koyar (├Ârne─čin, Java'n─▒n Math s─▒n─▒f statik y├Ântemleri gibi)
 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):
        """this could be outside the class, but we put it here 
just because we think it is logically related to the class."""
        return atan(y, x)


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

angle = Point.angle(3, 2)

 

7







@classmethod: o s─▒n─▒f─▒n yaratt─▒─č─▒ t├╝m ├Ârneklere ortak bir k├╝resel eri┼čim olu┼čturmak i├žin kullan─▒labilir ..... birden fazla kullan─▒c─▒n─▒n kayd─▒n─▒ g├╝ncellemek gibi .... ├ľzellikle singletons olu┼čtururken ful kulland─▒─č─▒n─▒ da buldum ..: )

@static method: s─▒n─▒fla veya ├Ârnekle ili┼čkilendirilen s─▒n─▒fla ilgisi yoktur ... ancak okunabilirlik i├žin statik y├Ântemi kullanabilirsiniz


6







Aradaki fark─▒ d├╝┼č├╝nmek isteyebilirsiniz:

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

ve

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

Bu python2 ve python3 aras─▒nda de─či┼čti:

python2:

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

python3:

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

Dolay─▒s─▒yla, @staticmethod yaln─▒zca s─▒n─▒ftan do─črudan ├ža─čr─▒lan y├Ântemlerin kullan─▒lmas─▒ python3'te iste─če ba─čl─▒ hale gelmi┼čtir. Bunlar─▒ hem s─▒n─▒ftan hem de s─▒n─▒ftan aramak istiyorsan─▒z, @staticmethod dekorat├Âr kullanman─▒z gerekir .

Di─čer davalar unutbus cevab─▒ ile iyi ├Ârt├╝lm├╝┼čt├╝r.


4







Katk─▒m @classmethod , @staticmethod bir ├Ârne─čin nas─▒l dolayl─▒ olarak ├ža─čr─▒ yapabildi─čini i├žeren ├Ârnek y├Ântemler aras─▒ndaki fark─▒ g├Âsterir @staticmethod . Ancak dolayl─▒ @staticmethod olarak bir ├Ârne─či ├ža─č─▒rmak yerine, onu ├Âzel yapmak daha "pitonik" olabilir. ├ľzel bir y├Ântemle bir ┼čey almak burada g├Âsterilmemi┼čtir, ancak temelde ayn─▒ kavramd─▒r.

 #!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)
'''
"""
 

3







Ad─▒ndan da anla┼č─▒laca─č─▒ gibi, s─▒n─▒f y├Ântemleri, nesnelerde de─čil s─▒n─▒flarda de─či┼čiklik yapmak i├žin kullan─▒l─▒r. S─▒n─▒flarda de─či┼čiklik yapmak i├žin, s─▒n─▒flar─▒ bu ┼čekilde g├╝ncelledi─činiz i├žin s─▒n─▒f niteliklerini de─či┼čtirecekler (nesne niteliklerini de─čil). S─▒n─▒f y├Ântemlerinin s─▒n─▒f─▒ (geleneksel olarak 'cls' ile g├Âsterilen) birinci arg├╝man olarak almas─▒n─▒n nedeni budur.

 class A(object):
    m=54

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

Statik y├Ântemler ise s─▒n─▒fa ba─čl─▒ olmayan i┼člevleri yerine getirmek i├žin kullan─▒l─▒r, yani s─▒n─▒f de─či┼čkenlerini okumaz veya yazmazlar. Bu nedenle, statik y├Ântemler s─▒n─▒flar─▒ arg├╝man olarak kabul etmez. S─▒n─▒flar─▒n, s─▒n─▒f─▒n amac─▒ ile do─črudan ilgili olmayan i┼člevleri yerine getirebilmesi i├žin kullan─▒l─▒rlar.

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

2







@Staticmethod tam anlam─▒yla farkl─▒ g├Âr├╝┼čler sa─člayan analiz edin .

Bir s─▒n─▒f─▒n normal bir y├Ântemi , ├Ârne─či ilk arg├╝man olarak alan ├Ârt├╝k bir dinamik y├Ântemdir.
Buna kar┼č─▒l─▒k, statik bir metot ├Ârne─či ilk arg├╝man olarak kabul etmez, bu y├╝zden 'statik' denir .

Statik bir metot, ger├žekten normal bir fonksiyondur, s─▒n─▒f tan─▒m─▒n─▒n d─▒┼č─▒ndakilerle ayn─▒d─▒r.
Neyse ki, uyguland─▒─č─▒ yere daha yak─▒n durmak i├žin s─▒n─▒fa grupland─▒r─▒lm─▒┼čs─▒n─▒z ya da bulmak i├žin etrafa kayabilirsiniz.


1







─░Python'daki ayn─▒ y├Ântemlerle h─▒zl─▒ca kesmek, @staticmethod marjinal performans kazanc─▒n─▒ (nanosaniye cinsinden) verdi─čini g├Âsterir , ancak bunun ba┼čka bir i┼člevi yoktur. Ayr─▒ca, herhangi bir performans kazanc─▒ muhtemelen staticmethod() derleme s─▒ras─▒nda y├Ântemin ek i┼členmesiyle (bir komut dosyas─▒ ├žal─▒┼čt─▒rd─▒─č─▒n─▒zda herhangi bir kod y├╝r├╝t├╝lmesinden ├Ânce ger├žekle┼čir) ek olarak silinir .

Kod okunabilirli─či i├žin @staticmethod , y├Ânteminiz nanosaniyelerin say─▒ld─▒─č─▒ i┼č y├╝klerinde kullan─▒lmayaca─č─▒ s├╝rece ka├ž─▒naca─č─▒m .


-6



─░lgili yay─▒nlar


Spring Framework'de @Inject ve @Outowired aras─▒ndaki fark nedir? Hangisi hangi ko┼čulda kullan─▒lacak?

Typeof ve instanceof aras─▒ndaki fark nedir ve biri di─čerine ne zaman kullan─▒lmal─▒d─▒r?

Map ve flatMap ve her biri i├žin iyi bir kullan─▒m durumu aras─▒ndaki fark nedir?

Javac ve Eclipse derleyicisi aras─▒ndaki fark nedir?

Read () ve recv () ile ve G├Ânderen () ve write () Aras─▒ndaki Fark Nedir?

Yineleyici ile yinelenebilir aras─▒ndaki fark nedir ve nas─▒l kullan─▒l─▒r?

Tek Y├Ânl├╝ ve ├çift Y├Ânl├╝ JPA ve Hibernate dernekleri aras─▒ndaki fark nedir?

ÔÇťAfter_createÔÇŁ ve ÔÇťafter_saveÔÇŁ ile ne zaman kullan─▒laca─č─▒ aras─▒ndaki fark nedir?

C++ STL'deki const_iterator ve const olmayan yineleyici aras─▒ndaki fark nedir?

JPA ve Hibernate'de persist () ile merge () aras─▒ndaki fark nedir?

Etiketle ilgili di─čer sorular [python]


PythonÔÇÖdaki bir istisnay─▒ elle olu┼čturma

IE10'un belirli alanlardaki ÔÇťalan─▒n─▒ temizleÔÇŁ X d├╝─čmesi kald─▒r─▒ls─▒n m─▒?

Git ┼čubelerini ana cihazdan g├╝ncelle

IntelliJ, fareyi JavaDocs ara├ž ipucunu g├Âsterme

Bir int de─čerini Go'da dizeye nas─▒l d├Ân├╝┼čt├╝rebilirim?

Performans testi i├žin tam zamanl─▒ ├Âl├ž├╝m [yinelenen]

Bir dosyan─▒n MD5 sa─člama toplam─▒ olu┼čturma

Node.js dosyas─▒nda ÔÇťprocess.stdout.writeÔÇŁ ve ÔÇťconsole.logÔÇŁ aras─▒ndaki fark?

Bir dizideki bo┼č elemanlar─▒ nas─▒l kald─▒rabilirim?

MySQL'de ROW_NUMBER ()