Python'da metas─▒n─▒flar nelerdir?


Al─▒nan cevaba git


Metas─▒n─▒flar nelerdir ve bunlar─▒ ne i├žin kullan─▒yoruz?


5365









Cevap say─▒s─▒n─▒ say: 16






Bir metaclass bir s─▒n─▒f─▒n s─▒n─▒f─▒d─▒r. Bir s─▒n─▒f, bir s─▒n─▒f ├Ârne─činin (yani bir nesnenin) nas─▒l davranaca─č─▒n─▒, bir metaclass ise bir s─▒n─▒f─▒n nas─▒l davranaca─č─▒n─▒ tan─▒mlar. Bir s─▒n─▒f bir metaclass ├Ârne─čidir.

Python'da, metaclass'lar i├žin rasgele mermiler kullanabiliyorken ( Jerub'─▒n g├Âsterdi─či gibi ), daha iyi bir yakla┼č─▒m onu ÔÇőÔÇőger├žek bir s─▒n─▒f yapmakt─▒r. type Python'daki ola─čan metaclass't─▒r. type kendisi bir s─▒n─▒ft─▒r ve kendi t├╝r├╝d├╝r. type Python'daki gibi bir ┼čeyi yeniden yaratamazs─▒n─▒z , ancak Python biraz hile yapar. Python'da kendi metaclass'─▒n─▒z─▒ olu┼čturmak i├žin ger├žekten sadece alt s─▒n─▒f─▒ kullanmak istiyorsunuz type .

Bir metaclass en ├žok s─▒n─▒f fabrikas─▒ olarak kullan─▒l─▒r. S─▒n─▒f─▒ ├ža─č─▒rarak bir nesne olu┼čturdu─čunuzda Python, metaclass'─▒ ├ža─č─▒rarak yeni bir s─▒n─▒f ('class' deyimini ├žal─▒┼čt─▒rd─▒─č─▒nda) olu┼čturur. Bu nedenle normal __init__ ve __new__ metotlarla birle┼čti─činde, meta s─▒n─▒flar bir s─▒n─▒f olu┼čtururken 'yeni ┼čeyler bir kay─▒t defterine kaydettirmek veya s─▒n─▒f─▒ ba┼čka bir ┼čeyle de─či┼čtirmek gibi' ekstra ┼čeyler yapman─▒za izin verir.

─░fade class ├žal─▒┼čt─▒r─▒ld─▒─č─▒nda, Python ├Ânce class ifadenin g├Âvdesini normal bir kod blo─ču olarak y├╝r├╝t├╝r . Sonu├žta ortaya ├ž─▒kan ad alan─▒ (bir dikme), bulunacak s─▒n─▒f─▒n niteliklerini tutar. Meta s─▒n─▒f, yap─▒lacak olan s─▒n─▒f─▒n temel s─▒n─▒flar─▒na (metaclass'lar miras al─▒n─▒r), yap─▒lacak __metaclass__ olan s─▒n─▒f─▒n (varsa) veya __metaclass__ global de─či┼čkenin ├Âzniteli─čine bakarak belirlenir . Metaclass daha sonra onu ba┼člatmak i├žin s─▒n─▒f─▒n ad─▒, temelleri ve nitelikleri ile ├ža─čr─▒l─▒r.

Ancak, metas─▒n─▒flar asl─▒nda bir s─▒n─▒f─▒n t├╝r├╝n├╝ tan─▒mlar , bunun i├žin sadece bir fabrika de─čil, onlarla daha fazlas─▒n─▒ yapabilirsiniz. ├ľrne─čin, metaclass'taki normal y├Ântemleri tan─▒mlayabilirsiniz. Bu metaclass y├Ântemleri, bir ├Ârnek olmadan s─▒n─▒fta ├ža─čr─▒labilmeleri i├žin s─▒n─▒f metotlar─▒na benzerler, ancak s─▒n─▒f─▒n bir ├Ârne─činde ├ža─čr─▒lmayacaklar─▒ s─▒n─▒f metotlar─▒na benzemezler. metaclass'taki type.__subclasses__() bir y├Ânteme bir ├Ârnektir type . Ayr─▒ca, gibi normal 'Sihirli' y├Ântemleri tan─▒mlayabilir __add__ , __iter__ ve __getattr__ uygulamak veya de─či┼čtirmek nas─▒l s─▒n─▒f davranaca─č─▒n─▒ i├žin.

─░┼čte par├ža ve par├žalar─▒n toplu bir ├Ârne─či:

 def make_hook(f):
    """Decorator to turn 'foo' method into '__foo__'"""
    f.is_hook = 1
    return f

class MyType(type):
    def __new__(mcls, name, bases, attrs):

        if name.startswith('None'):
            return None

        # Go over attributes and see if they should be renamed.
        newattrs = {}
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, 'is_hook', 0):
                newattrs['__%s__' % attrname] = attrvalue
            else:
                newattrs[attrname] = attrvalue

        return super(MyType, mcls).__new__(mcls, name, bases, newattrs)

    def __init__(self, name, bases, attrs):
        super(MyType, self).__init__(name, bases, attrs)

        # classregistry.register(self, self.interfaces)
        print "Would register class %s now." % self

    def __add__(self, other):
        class AutoClass(self, other):
            pass
        return AutoClass
        # Alternatively, to autogenerate the classname as well as the class:
        # return type(self.__name__ + other.__name__, (self, other), {})

    def unregister(self):
        # classregistry.unregister(self)
        print "Would unregister class %s now." % self

class MyObject:
    __metaclass__ = MyType


class NoneSample(MyObject):
    pass

# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)

class Example(MyObject):
    def __init__(self, value):
        self.value = value
    @make_hook
    def add(self, other):
        return self.__class__(self.value + other.value)

# Will unregister the class
Example.unregister()

inst = Example(10)
# Will fail with an AttributeError
#inst.unregister()

print inst + inst
class Sibling(MyObject):
    pass

ExampleSibling = Example + Sibling
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__
 

2624







Nesne olarak s─▒n─▒flar

Metas─▒n─▒flar─▒ anlamadan ├Ânce, Python'da ders vermeniz gerekir. Ve Python'un, Smalltalk dilinden ├Âd├╝n├ž al─▒nan s─▒n─▒flar─▒n ne oldu─čuna dair ├žok tuhaf bir fikri vard─▒r.

├ço─ču dilde, s─▒n─▒flar bir nesnenin nas─▒l ├╝retilece─čini tan─▒mlayan sadece kod par├žalar─▒d─▒r. Bu Python'da da do─čru:

 >>> class ObjectCreator(object):
...       pass
...

>>> my_object = ObjectCreator()
>>> print(my_object)
<__main__.ObjectCreator object at 0x8974f2c>
 

Ancak s─▒n─▒flar Python'da oldu─čundan daha fazla. S─▒n─▒flar da nesnelerdir.

Evet nesneler.

Anahtar s├Âzc├╝─č├╝ kullan─▒r kullanmaz class , Python ├žal─▒┼čt─▒r─▒r ve bir NESNE olu┼čturur. Talimat

 >>> class ObjectCreator(object):
...       pass
...
 

bellekte "ObjectCreator" ad─▒nda bir nesne olu┼čturur.

Bu nesnenin (s─▒n─▒f) kendisi nesneler olu┼čturabilir (├Ârnekler) ve bu y├╝zden bir s─▒n─▒ft─▒r .

Ama yine de, bu bir nesne ve bu nedenle:

  • bir de─či┼čkene atayabilirsiniz
  • kopyalayabilirsin
  • ona ├Âzellikler ekleyebilirsiniz
  • Bir i┼člev parametresi olarak iletebilirsiniz

├ľrne─čin:

 >>> print(ObjectCreator) # you can print a class because it's an object
<class '__main__.ObjectCreator'>
>>> def echo(o):
...       print(o)
...
>>> echo(ObjectCreator) # you can pass a class as a parameter
<class '__main__.ObjectCreator'>
>>> print(hasattr(ObjectCreator, 'new_attribute'))
False
>>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class
>>> print(hasattr(ObjectCreator, 'new_attribute'))
True
>>> print(ObjectCreator.new_attribute)
foo
>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable
>>> print(ObjectCreatorMirror.new_attribute)
foo
>>> print(ObjectCreatorMirror())
<__main__.ObjectCreator object at 0x8997b4c>
 

Dinamik olarak s─▒n─▒flar olu┼čturma

S─▒n─▒flar nesne oldu─čundan, onlar─▒ an─▒nda, herhangi bir nesne gibi olu┼čturabilirsiniz.

─░lk ├Ânce, a┼ča─č─▒dakileri kullanarak bir i┼člevde bir s─▒n─▒f olu┼čturabilirsiniz class :

 >>> def choose_class(name):
...     if name == 'foo':
...         class Foo(object):
...             pass
...         return Foo # return the class, not an instance
...     else:
...         class Bar(object):
...             pass
...         return Bar
...
>>> MyClass = choose_class('foo')
>>> print(MyClass) # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print(MyClass()) # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>
 

Ama o kadar dinamik de─čil, ├ž├╝nk├╝ hala t├╝m s─▒n─▒f─▒ kendiniz yazmak zorundas─▒n─▒z.

S─▒n─▒flar nesne oldu─čundan, bir ┼čey taraf─▒ndan ├╝retilmeleri gerekir.

class Anahtar s├Âzc├╝─č├╝ kulland─▒─č─▒n─▒zda , Python bu nesneyi otomatik olarak olu┼čturur. Ancak Python'daki ├žo─ču ┼čeyde oldu─ču gibi, bunu manuel olarak yapman─▒z i├žin bir yol sunar.

Fonksiyonu hat─▒rlad─▒n type m─▒? Hangi t├╝r bir nesne oldu─čunu bilmenizi sa─člayan eski fonksiyon:

 >>> print(type(1))
<type 'int'>
>>> print(type("1"))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>
 

Eh, type bu da an─▒nda s─▒n─▒f olu┼čturabilece─čini bamba┼čka bir yetene─či vard─▒r. type Bir s─▒n─▒f─▒n tan─▒m─▒n─▒ parametre olarak alabilir ve bir s─▒n─▒f d├Ând├╝rebilir.

(Biliyorum, ayn─▒ i┼člevin, aktard─▒─č─▒n─▒z parametrelere g├Âre tamamen farkl─▒ iki kullan─▒m─▒ olabilir. Python'daki geriye d├Ân├╝k uyumluluktan dolay─▒ bu bir sorun)

type bu ┼čekilde ├žal─▒┼č─▒r:

 type(name of the class,
     tuple of the parent class (for inheritance, can be empty),
     dictionary containing attributes names and values)
 

├ľrne─čin:

 >>> class MyShinyClass(object):
...       pass
 

manuel olarak bu ┼čekilde olu┼čturulabilir:

 >>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print(MyShinyClass)
<class '__main__.MyShinyClass'>
>>> print(MyShinyClass()) # create an instance with the class
<__main__.MyShinyClass object at 0x8997cec>
 

S─▒n─▒f─▒n referans─▒ olarak "MyShinyClass" ─▒ s─▒n─▒f─▒n ad─▒ ve de─či┼čken olarak kulland─▒─č─▒m─▒z─▒ fark edeceksiniz. Farkl─▒ olabilirler, ancak i┼čleri karma┼č─▒kla┼čt─▒rmak i├žin hi├žbir neden yoktur.

type S─▒n─▒f─▒n ├Âzelliklerini tan─▒mlamak i├žin bir s├Âzl├╝k kabul eder. Yani:

 >>> class Foo(object):
...       bar = True
 

Çevrilebilir:

 >>> Foo = type('Foo', (), {'bar':True})
 

Ve normal bir s─▒n─▒f olarak kullan─▒l─▒r:

 >>> print(Foo)
<class '__main__.Foo'>
>>> print(Foo.bar)
True
>>> f = Foo()
>>> print(f)
<__main__.Foo object at 0x8a9b84c>
>>> print(f.bar)
True
 

Ve elbette, bundan miras alabilirsiniz, yani:

 >>>   class FooChild(Foo):
...         pass
 

olabilir:

 >>> FooChild = type('FooChild', (Foo,), {})
>>> print(FooChild)
<class '__main__.FooChild'>
>>> print(FooChild.bar) # bar is inherited from Foo
True
 

Sonunda s─▒n─▒f─▒n─▒za y├Ântemler eklemek istersiniz. Sadece uygun imzayla bir i┼člev tan─▒mlay─▒n ve onu nitelik olarak atay─▒n.

 >>> def echo_bar(self):
...       print(self.bar)
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True
 

S─▒n─▒f─▒ dinamik olarak olu┼čturduktan sonra, normalde olu┼čturulmu┼č bir s─▒n─▒f nesnesine y├Ântemler eklemek gibi, daha da fazla y├Ântem ekleyebilirsiniz.

 >>> def echo_bar_more(self):
...       print('yet another method')
...
>>> FooChild.echo_bar_more = echo_bar_more
>>> hasattr(FooChild, 'echo_bar_more')
True
 

Nereye gitti─čimizi g├Âr├╝yorsunuz: Python'da s─▒n─▒flar nesnedir ve dinamik olarak, an─▒nda bir s─▒n─▒f olu┼čturabilirsiniz.

Bu, anahtar kelimeyi kullan─▒rken Python'un yapt─▒─č─▒ class ve bir metaclass kullanarak yapt─▒─č─▒ ┼čeydir.

Metaclass nedir (nihayet)

Meta g├Âzl├╝kler, s─▒n─▒flar─▒ olu┼čturan 'e┼čyalard─▒r.

Nesneleri olu┼čturmak i├žin s─▒n─▒flar─▒ tan─▒mlars─▒n, de─čil mi?

Ancak Python s─▒n─▒flar─▒n─▒n nesne oldu─čunu ├Â─črendik.

Metaklas, bu nesneleri yaratan ┼čeydir. Onlar s─▒n─▒flar─▒n s─▒n─▒flar─▒d─▒r, onlar─▒ ┼ču ┼čekilde hayal edebilirsiniz:

 MyClass = MetaClass()
my_object = MyClass()
 

Bunun type gibi bir ┼čey yapman─▒za izin verdi─čini g├Ârd├╝n├╝z :

 MyClass = type('MyClass', (), {})
 

├ç├╝nk├╝ fonksiyon type asl─▒nda bir metaclass. type Python sahne arkas─▒ndaki t├╝m s─▒n─▒flar─▒ olu┼čturmak i├žin kulland─▒─č─▒ metaclass.

┼×imdi neden halt─▒n k├╝├ž├╝k harfle yaz─▒ld─▒─č─▒n─▒ merak ediyorsun, de─čil Type mi?

San─▒r─▒m, bununla tutarl─▒l─▒k meselesi, str dizge nesnelerini int yaratan s─▒n─▒f ve tamsay─▒l─▒ nesneler yaratan s─▒n─▒f var. type sadece s─▒n─▒f nesnelerini yaratan s─▒n─▒ft─▒r.

Bunu, __class__ niteli─či kontrol ederek g├Âr├╝rs├╝n├╝z .

Her ┼čey ve her ┼čeyi kastediyorum, Python'da bir nesnedir. Bu, ints, stringler, fonksiyonlar ve s─▒n─▒flar─▒ i├žerir. Hepsi nesnelerdir. Ve hepsi bir s─▒n─▒ftan yarat─▒ld─▒:

 >>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>> foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
 

┼×imdi, __class__ herhangi biri __class__ nedir?

 >>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>
 

Yani, bir metaclass sadece s─▒n─▒f nesnelerini yaratan ┼čeydir.

─░sterseniz buna 's─▒n─▒f fabrikas─▒' diyebilirsiniz.

type Python'un kulland─▒─č─▒ yerle┼čik metaclass't─▒r, ancak elbette kendi metaclass'─▒n─▒z─▒ olu┼čturabilirsiniz.

__metaclass__ nitelik

Python 2'de, __metaclass__ bir s─▒n─▒f yazarken bir ├Âzellik ekleyebilirsiniz (Python 3 s├Âzdizimi i├žin bir sonraki b├Âl├╝me bak─▒n):

 class Foo(object):
    __metaclass__ = something...
    [...]
 

Bunu yaparsan─▒z, Python s─▒n─▒f─▒ olu┼čturmak i├žin metaclass'─▒ kullan─▒r Foo .

Dikkat et, ├žok zor.

├ľnce sen yazars─▒n class Foo(object) , fakat s─▒n─▒f nesnesi Foo hen├╝z haf─▒zada yarat─▒lmaz.

Python __metaclass__ s─▒n─▒f tan─▒m─▒nda arayacakt─▒r . Onu bulursa, nesne s─▒n─▒f─▒n─▒ olu┼čturmak i├žin kullan─▒r Foo . type Olmazsa, s─▒n─▒f─▒ olu┼čturmak i├žin kullanacakt─▒r .

Bunu birka├ž kez oku.

Ne zaman yapars─▒n:

 class Foo(Bar):
    pass
 

Python a┼ča─č─▒dakileri yapar:

─░├žinde bir __metaclass__ ├Âzellik var Foo m─▒?

E─čer ├Âyleyse, bellekte bir s─▒n─▒f nesnesi olu┼čturun (bir s─▒n─▒f nesnesi dedim, burada benimle kal), i├žinde Foo olan─▒ kullanarak ad─▒n─▒ yaz─▒n __metaclass__ .

Python bulamazsa __metaclass__ , __metaclass__ MOD├ťL d├╝zeyinde bir seviye arayacak ve ayn─▒ ┼čeyi yapmaya ├žal─▒┼čacakt─▒r (ancak yaln─▒zca herhangi bir ┼čeyi devralmayan, temelde eski stil s─▒n─▒flar─▒ i├žin).

Sonra herhangi bulamazsa __metaclass__ hi├ž bu kullanaca─č─▒z Bar 's (birinci ebeveyn) (varsay─▒lan olabilir kendi metaclass type s─▒n─▒f nesnesi olu┼čturmak i├žin).

Burada dikkatli olun __metaclass__ nitelik miras olmayacak, ebeveynin metaclass ( Bar.__class__ ) olacakt─▒r. E─čer (ve olmayan ) ile yarat─▒lan Bar bir __metaclass__ nitelik kullan─▒l─▒rsa , alt s─▒n─▒flar bu davran─▒┼č─▒ devralmaz. Bar type() type.__new__()

┼×imdi b├╝y├╝k soru ┼čudur, ne koyabilirsiniz __metaclass__ ?

Cevap: bir s─▒n─▒f olu┼čturabilecek bir ┼čey.

Ve bir s─▒n─▒f ne yaratabilir? type veya alt s─▒n─▒flar─▒ veya bunlar─▒ kullanan herhangi bir ┼čey.

Metal g├Âzl├╝kler in Python 3

Metaclass'─▒ ayarlamak i├žin kullan─▒lan s├Âzdizimi Python 3'te de─či┼čtirildi:

 class Foo(object, metaclass=something):
    ...
 

yani __metaclass__ ├Âzellik art─▒k temel s─▒n─▒flar listesindeki bir anahtar kelime arg├╝man─▒ lehine kullan─▒lm─▒yor.

Ancak metas─▒n─▒flar─▒n davran─▒┼č─▒ b├╝y├╝k ├Âl├ž├╝de ayn─▒ kal─▒r .

Python 3'teki metaclass'lara eklenen bir ┼čey, anahtar s├Âzc├╝k arg├╝manlar─▒ gibi nitelikleri bir metaclass'a da aktarabilirsiniz:

 class Foo(object, metaclass=something, kwarg1=value1, kwarg2=value2):
    ...
 

Python'un bunu nas─▒l ele ald─▒─č─▒na ili┼čkin a┼ča─č─▒daki b├Âl├╝m├╝ okuyun.

├ľzel metaclasses

Bir metaclass'─▒n as─▒l amac─▒, olu┼čturuldu─čunda s─▒n─▒f─▒ otomatik olarak de─či┼čtirmektir.

Bunu genellikle mevcut ba─člamla e┼čle┼čen s─▒n─▒flar olu┼čturmak istedi─činiz API'ler i├žin yapars─▒n─▒z.

Mod├╝l├╝n├╝zdeki t├╝m s─▒n─▒flar─▒n niteliklerini b├╝y├╝k harfle yazmas─▒ gerekti─čine karar verdi─činiz aptal bir ├Ârnek d├╝┼č├╝n├╝n. Bunu yapman─▒n birka├ž yolu vard─▒r, ancak bir yol __metaclass__ mod├╝l d├╝zeyinde ayarlamakt─▒r .

Bu ┼čekilde, bu mod├╝l├╝n t├╝m s─▒n─▒flar─▒ bu metaclass kullan─▒larak olu┼čturulacak ve metaclass'a t├╝m ├Âzellikleri b├╝y├╝k harfe d├Ân├╝┼čt├╝rmesini s├Âylemeliyiz.

Neyse ki, __metaclass__ asl─▒nda herhangi bir ├ža─čr─▒labilir olabilir, resmi bir s─▒n─▒f olmas─▒ gerekmez (Biliyorum, ad─▒nda 's─▒n─▒f─▒' olan bir ┼čeyin bir s─▒n─▒f olmas─▒ gerekmez, gitmesi gerekiyor ... ama bu yard─▒mc─▒ olur).

B├Âylece bir fonksiyon kullanarak basit bir ├Ârnekle ba┼člayaca─č─▒z.

 # the metaclass will automatically get passed the same argument
# that you usually pass to `type`
def upper_attr(future_class_name, future_class_parents, future_class_attr):
    """
      Return a class object, with the list of its attribute turned
      into uppercase.
    """

    # pick up any attribute that doesn't start with '__' and uppercase it
    uppercase_attr = {}
    for name, val in future_class_attr.items():
        if not name.startswith('__'):
            uppercase_attr[name.upper()] = val
        else:
            uppercase_attr[name] = val

    # let `type` do the class creation
    return type(future_class_name, future_class_parents, uppercase_attr)

__metaclass__ = upper_attr # this will affect all classes in the module

class Foo(): # global __metaclass__ won't work with "object" though
    # but we can define __metaclass__ here instead to affect only this class
    # and this will work with "object" children
    bar = 'bip'

print(hasattr(Foo, 'bar'))
# Out: False
print(hasattr(Foo, 'BAR'))
# Out: True

f = Foo()
print(f.BAR)
# Out: 'bip'
 

┼×imdi, ayn─▒s─▒n─▒ yapal─▒m, fakat bir metaclass i├žin ger├žek bir s─▒n─▒f kullanal─▒m:

 # remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type):
    # __new__ is the method called before __init__
    # it's the method that creates the object and returns it
    # while __init__ just initializes the object passed as parameter
    # you rarely use __new__, except when you want to control how the object
    # is created.
    # here the created object is the class, and we want to customize it
    # so we override __new__
    # you can do some stuff in __init__ too if you wish
    # some advanced use involves overriding __call__ as well, but we won't
    # see this
    def __new__(upperattr_metaclass, future_class_name,
                future_class_parents, future_class_attr):

        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return type(future_class_name, future_class_parents, uppercase_attr)
 

Ancak bu ger├žekten OOP de─čil. Biz diyoruz type do─črudan ve ge├žersiz k─▒labilir veya ebeveyni demiyorlar __new__ . Haydi Yapal─▒m ┼čunu:

 class UpperAttrMetaclass(type):

    def __new__(upperattr_metaclass, future_class_name,
                future_class_parents, future_class_attr):

        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        # reuse the type.__new__ method
        # this is basic OOP, nothing magic in there
        return type.__new__(upperattr_metaclass, future_class_name,
                            future_class_parents, uppercase_attr)
 

Ekstra arg├╝man─▒ fark etmi┼č olabilirsiniz upperattr_metaclass . Bu konuda ├Âzel bir ┼čey yok: __new__ daima tan─▒mland─▒─č─▒ s─▒n─▒f─▒, ilk parametre olarak al─▒r. T─▒pk─▒ self ├Ârne─či ilk parametre olarak alan s─▒radan y├Ântemlerde veya s─▒n─▒f y├Ântemleri i├žin tan─▒mlay─▒c─▒ s─▒n─▒fta oldu─ču gibi.

Elbette, burada kulland─▒─č─▒m isimler a├ž─▒kl─▒k u─čruna uzun, ama bunun gibi self , t├╝m arg├╝manlar─▒n geleneksel isimleri var. B├Âylece ger├žek bir ├╝retim metaclass ┼č├Âyle g├Âr├╝n├╝r:

 class UpperAttrMetaclass(type):

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return type.__new__(cls, clsname, bases, uppercase_attr)
 

super Kal─▒t─▒msall─▒─č─▒ kolayla┼čt─▒racak ┼čekilde kullanarak daha temiz hale getirebiliriz (├ž├╝nk├╝ evet, metas─▒n─▒flardan miras alan, t├╝rden miras alan bir metaclass'a sahip olabilirsiniz):

 class UpperAttrMetaclass(type):

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)
 

Oh, ve e─čer python 3'te bu ├ža─čr─▒y─▒, anahtar s├Âzc├╝k arg├╝manlar─▒ ile yaparsan─▒z, ┼č├Âyle:

 class Foo(object, metaclass=Thing, kwarg1=value1):
    ...
 

Bunu kullanmak i├žin metaclass i├žindeki ├ževirir:

 class Thing(type):
    def __new__(cls, clsname, bases, dct, kwargs1=default):
        ...
 

Bu kadar. Metaclass hakk─▒nda daha fazla bir ┼čey yok.

Metalllass kullanan kodun karma┼č─▒kl─▒─č─▒n─▒n arkas─▒ndaki neden metaclasslar de─čil, introspeksiyona dayanan, kal─▒t─▒m manip├╝le __dict__ , vb. Gibi de─či┼čkenler yapmak i├žin genellikle metalllass kullan─▒yorsunuz .

Ger├žekten de, metas─▒n─▒flar ├Âzellikle kara b├╝y├╝ yapmakta ve dolay─▒s─▒yla karma┼č─▒k ┼čeyleri yapmakta kullan─▒┼čl─▒d─▒r. Ancak kendi ba┼člar─▒na, basittirler:

  • bir s─▒n─▒f olu┼čumunu engellemek
  • s─▒n─▒f─▒ de─či┼čtir
  • de─či┼čtirilmi┼č s─▒n─▒f─▒ d├Ând├╝r

Neden i┼člev yerine meta s─▒n─▒flar─▒ kullan─▒yorsunuz?

Yana __metaclass__ herhangi ├ža─čr─▒labilir kabul edebilir a├ž─▒k├ža daha karma┼č─▒kt─▒r ├ž├╝nk├╝, neden bir s─▒n─▒f kullanmak istiyorsunuz?

Bunu yapmak i├žin birka├ž neden var:

  • Ama├ž a├ž─▒kt─▒r. Okudu─čunda UpperAttrMetaclass(type) ne takip edece─čini biliyorsun.
  • OOP'yi kullanabilirsiniz. Metaclass, metaclass ├Â─česini devralabilir, ├╝st y├Ântemleri ge├žersiz k─▒labilir. Metas─▒n─▒flar metas─▒n─▒flar─▒ bile kullanabilir.
  • Bir s─▒n─▒f─▒n alt s─▒n─▒flar─▒, bir metaclass s─▒n─▒f─▒ belirtirseniz, ancak bir metaclass i┼čleviyle belirtilmemi┼čse, metaclass ├Ârnekleridir.
  • Kodunuzu daha iyi yap─▒land─▒rabilirsiniz. Metaclass'lar─▒ asla yukar─▒daki ├Ârnekteki gibi ├Ânemsiz ┼čeyler i├žin kullanmazs─▒n─▒z. Genellikle karma┼č─▒k bir ┼čey i├žin. Birka├ž y├Ântemi yapma ve bunlar─▒ bir s─▒n─▒fta gruplama yetene─čine sahip olmak, kodu okumay─▒ kolayla┼čt─▒rmak i├žin ├žok yararl─▒d─▒r.
  • Ba─člayabilirsiniz __new__ , __init__ ve __call__ . Farkl─▒ ┼čeyler yapmana izin verecek. Genellikle hepsini yapabiliyor olsan─▒z bile __new__ , baz─▒ insanlar kullan─▒m─▒ daha da rahat __init__ .
  • Bunlara metaclass denir, kahretsin! Bir anlam─▒ olmal─▒!

Neden metas─▒n─▒flar─▒ kulland─▒n?

┼×imdi b├╝y├╝k soru. Neden baz─▒ gizli hatalara e─čilimli bir ├Âzellik kullan─▒yorsunuz?

Genelde yapmazs─▒n:

Meta g├Âzl├╝kler, kullan─▒c─▒lar─▒n% 99'unun asla endi┼čelenmemesi gereken daha derin bir sihirdir. Onlara ihtiya├ž duyup duymad─▒─č─▒n─▒z─▒ merak ediyorsan─▒z, (ger├žekten ihtiyac─▒ olan insanlar kendilerine ihtiya├ž duyduklar─▒n─▒ kesin olarak bilirler ve nedenleriyle ilgili bir a├ž─▒klama yapmalar─▒ gerekmez).

Python Guru Tim Peters

Bir metaclass i├žin ana kullan─▒m durumu bir API olu┼čturmakt─▒r. Bunun tipik bir ├Ârne─či Django ORM'dir.

B├Âyle bir ┼čeyi tan─▒mlaman─▒za izin verir:

 class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
 

Ama bunu yaparsan:

 guy = Person(name='bob', age='35')
print(guy.age)
 

Bir IntegerField nesneyi d├Ând├╝rmez . Bir d├Ând├╝r├╝r int ve do─črudan veritaban─▒ndan bile alabilir.

Bu m├╝mk├╝nd├╝r ├ž├╝nk├╝ models.Model tan─▒mlay─▒p __metaclass__ ve d├Ânecek biraz sihir kullanan Person bir veritaban─▒ alan─▒na karma┼č─▒k bir kanca i├žine sadece basit ifadelerle tan─▒mlad─▒.

Django, basit bir API'yi a├ž─▒─ča ├ž─▒kararak ve metas─▒n─▒flar─▒ kullanarak, sahnelerin arkas─▒ndaki as─▒l i┼či yapmak i├žin bu API'den kodu yeniden olu┼čturarak karma┼č─▒k bir ┼čeyi basitle┼čtirir.

Son kelime

─░lk ├Ânce, s─▒n─▒flar─▒n ├Ârnek olu┼čturabilecek nesneler oldu─čunu biliyorsunuz.

Asl─▒nda, s─▒n─▒flar─▒n kendileri birer ├Ârnek. Metaclasses.

 >>> class Foo(object): pass
>>> id(Foo)
142630324
 

Her ┼čey Python'da bir nesnedir ve hepsi s─▒n─▒f ├Ârnekleri veya metaclass ├Ârnekleridir.

D─▒┼č─▒nda type .

type Asl─▒nda kendi metaclass. Bu, saf Python ile yeniden ├╝retebilece─činiz bir ┼čey de─čildir ve uygulama d├╝zeyinde biraz hile yaparak yap─▒l─▒r.

─░kincisi, metas─▒n─▒flar karma┼č─▒kt─▒r. Bunlar─▒ ├žok basit s─▒n─▒f de─či┼čiklikleri i├žin kullanmak istemeyebilirsiniz. ─░ki farkl─▒ teknik kullanarak s─▒n─▒flar─▒ de─či┼čtirebilirsiniz:

S─▒n─▒f de─či┼čikli─čine ihtiya├ž duydu─čunuz zaman─▒n% 99'unda, bunlar─▒ kullanmaktan daha iyi olursunuz.

Ancak, zaman─▒n% 98'i, hi├žbir ┼čekilde s─▒n─▒f de─či┼čikli─či yapman─▒za gerek yoktur.


6471







Unutmay─▒n, bu cevap Python 2.x i├žin, 2008'de yaz─▒ld─▒─č─▒ gibi, metas─▒n─▒flar 3.x'te biraz farkl─▒d─▒r.

Metaclasses 's─▒n─▒f' ├žal─▒┼čmas─▒n─▒ sa─člayan gizli sos. Yeni bir stil nesnesi i├žin varsay─▒lan metaclass 'tip' olarak adland─▒r─▒l─▒r.

 class type(object)
  |  type(object) -> the object's type
  |  type(name, bases, dict) -> a new type
 

Metaclasses 3 args al─▒r. ' isim ', ' ├╝s ' ve ' dikt '

─░┼čte s─▒rr─▒n ba┼člad─▒─č─▒ yer. Bu ├Ârnek s─▒n─▒f tan─▒m─▒nda ad─▒n, temellerin ve dize nereden geldi─čine bak─▒n.

 class ThisIsTheName(Bases, Are, Here):
    All_the_code_here
    def doesIs(create, a):
        dict
 

' Class: ' in nas─▒l ├ža─č─▒rd─▒─č─▒n─▒ g├Âsterecek bir metaclass tan─▒mlayal─▒m .

 def test_metaclass(name, bases, dict):
    print 'The Class Name is', name
    print 'The Class Bases are', bases
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys()

    return "yellow"

class TestName(object, None, int, 1):
    __metaclass__ = test_metaclass
    foo = 1
    def baz(self, arr):
        pass

print 'TestName = ', repr(TestName)

# output => 
The Class Name is TestName
The Class Bases are (<type 'object'>, None, <type 'int'>, 1)
The dict has 4 elems, the keys are ['baz', '__module__', 'foo', '__metaclass__']
TestName =  'yellow'
 

Ve ┼čimdi, asl─▒nda bir anlam ifade eden bir ├Ârnek, bu, de─či┼čkenleri s─▒n─▒fta ayarlanan ve ÔÇťYokÔÇŁ olarak ayarlanan ÔÇť├ÂzniteliklerÔÇŁ listesindeki de─či┼čkenleri otomatik olarak yapacakt─▒r.

 def init_attributes(name, bases, dict):
    if 'attributes' in dict:
        for attr in dict['attributes']:
            dict[attr] = None

    return type(name, bases, dict)

class Initialised(object):
    __metaclass__ = init_attributes
    attributes = ['foo', 'bar', 'baz']

print 'foo =>', Initialised.foo
# output=>
foo => None
 

'Initalised' i┼čleminin 'metaclass'─▒ alarak kazand─▒─č─▒ sihir davran─▒┼č─▒n─▒n Initalised'in init_attributes bir alt s─▒n─▒f─▒na ge├žmedi─čine dikkat edin.

S─▒n─▒f olu┼čturuldu─čunda nas─▒l bir eylem ger├žekle┼čtiren bir metaclass yapmak i├žin 'type' alt s─▒n─▒f─▒n─▒ g├Âsterebilece─činizi g├Âsteren daha somut bir ├Ârnek. Bu olduk├ža zor:

 class MetaSingleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
        return cls.instance

class Foo(object):
    __metaclass__ = MetaSingleton

a = Foo()
b = Foo()
assert a is b
 

377







Di─čerleri metas─▒n─▒flar─▒n nas─▒l ├žal─▒┼čt─▒─č─▒n─▒ ve Python tipi sisteme nas─▒l uydu─čunu a├ž─▒klad─▒lar. ─░┼čte ne i├žin kullan─▒labileceklerine bir ├Ârnek. Yazd─▒─č─▒m bir test ├žer├ževesinde, s─▒n─▒flar─▒n tan─▒mland─▒─č─▒ s─▒ray─▒ takip etmek istedim, b├Âylece onlar─▒ daha sonra bu s─▒raya g├Âre ba┼člatabilirdim. Bir metaclass kullanarak bunu yapmak en kolay buldum.

 class MyMeta(type):

    counter = 0

    def __init__(cls, name, bases, dic):
        type.__init__(cls, name, bases, dic)
        cls._order = MyMeta.counter
        MyMeta.counter += 1

class MyType(object):              # Python 2
    __metaclass__ = MyMeta

class MyType(metaclass=MyMeta):    # Python 3
    pass
 

Alt s─▒n─▒f─▒ olan her ┼čey , s─▒n─▒flar─▒n tan─▒mland─▒─č─▒ s─▒ray─▒ kaydeden MyType bir s─▒n─▒f niteli─či al─▒r _order .


152







Metaclasses i├žin bir kullan─▒m otomatik olarak bir ├Ârne─če yeni ├Âzellikler ve y├Ântemler eklemektir.

├ľrne─čin, Django modellerine bakarsan─▒z, tan─▒mlar─▒ biraz kafa kar─▒┼čt─▒r─▒c─▒ g├Âr├╝n├╝yor. Yaln─▒zca s─▒n─▒f ├Âzelliklerini tan─▒ml─▒yormu┼čsunuz gibi g├Âr├╝n├╝yor:

 class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
 

Bununla birlikte, ├žal─▒┼čma zaman─▒nda Person nesneleri her t├╝rl├╝ faydal─▒ y├Ântemle doldurulur. Baz─▒ ┼ča┼č─▒rt─▒c─▒ metaclassery i├žin kayna─ča bak─▒n .


149







ONLamp'─▒n metaclass programlamaya giri┼činin iyi yaz─▒lm─▒┼č oldu─čunu d├╝┼č├╝n├╝yorum ve zaten birka├ž ya┼č─▒nda olmas─▒na ra─čmen konuya ger├žekten iyi bir giri┼č yapt─▒─č─▒n─▒ d├╝┼č├╝n├╝yorum.

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html ( https://web.archive.org/web/20080206005253/http://www.onlamp adresinde ar┼čivlenmi┼čtir) . com / pub / a / python / 2003/04/17 / metaclasses.html )

K─▒sacas─▒: Bir s─▒n─▒f, ├Ârne─čin olu┼čturulmas─▒ i├žin bir taslakt─▒r, bir metaclass, bir s─▒n─▒f olu┼čturulmas─▒ i├žin bir taslakt─▒r. Python s─▒n─▒flar─▒nda bu davran─▒┼č─▒ etkinle┼čtirmek i├žin birinci s─▒n─▒f nesneler olmas─▒ gerekti─či kolayca g├Âr├╝lebilir.

Hi├ž kendimden bir tane yazmad─▒m, ama bence en iyi metaclass kullan─▒mlar─▒ndan biri Django ├žer├ževesinde g├Âr├╝lebilir . Model s─▒n─▒flar─▒, yeni modeller veya form s─▒n─▒flar─▒ yazmak i├žin bildirimsel bir stil sa─člamak i├žin bir metaclass yakla┼č─▒m─▒ kullan─▒r. Metaclass s─▒n─▒f─▒ yarat─▒rken, t├╝m ├╝yeler s─▒n─▒f─▒n kendisini ki┼čiselle┼čtirme olana─č─▒na sahip olur.

S├Âylenecek ┼čey ┼čudur: E─čer metas─▒n─▒flar─▒n ne oldu─čunu bilmiyorsan─▒z, onlara ihtiya├ž duymama ihtimaliniz % 99'dur.


109







Metas─▒n─▒f nedir? Onlar─▒ ne i├žin kullan─▒yorsun?

TLDR: Bir metaclass bir s─▒n─▒ftaki davran─▒┼č─▒ ba┼člat─▒r ve tan─▒mlar, bir s─▒n─▒ftaki davran─▒┼č─▒ ba┼člat─▒r ve tan─▒mlar.

pseudocode:

 >>> Class(...)
instance
 

Yukar─▒daki tan─▒d─▒k gelmelidir. Peki nereden Class geliyor? Bu bir metaclass ├Ârne─čidir (ayr─▒ca s├Âzde kod):

 >>> Metaclass(...)
Class
 

Ger├žek kodda, varsay─▒lan metaclass'─▒, type bir s─▒n─▒f─▒ ba┼člatmak i├žin gereken her ┼čeyi ve bir s─▒n─▒fa ge├žebiliriz:

 >>> type('Foo', (object,), {}) # requires a name, bases, and a namespace
<class '__main__.Foo'>
 

Farkl─▒ koyarak

  • Bir s─▒n─▒f, bir metaclass olarak bir s─▒n─▒fa oldu─ču gibi bir ├Ârnektir.

    Bir nesneyi ba┼člatt─▒─č─▒m─▒zda, bir ├Ârnek al─▒r─▒z:

     >>> object()                          # instantiation of class
    <object object at 0x7f9069b4e0b0>     # instance
     

    Benzer ┼čekilde, varsay─▒lan metaclass ile a├ž─▒k├ža bir s─▒n─▒f tan─▒mlad─▒─č─▒m─▒zda type , onu ba┼člat─▒r─▒z:

     >>> type('Object', (object,), {})     # instantiation of metaclass
    <class '__main__.Object'>             # instance
     
  • Ba┼čka bir deyi┼čle, s─▒n─▒f bir metaclass ├Ârne─čidir:

     >>> isinstance(object, type)
    True
     
  • ├ť├ž├╝nc├╝ bir y├Ântemle, bir metaclass bir s─▒n─▒f─▒n s─▒n─▒f─▒d─▒r.

     >>> type(object) == type
    True
    >>> object.__class__
    <class 'type'>
     

Bir s─▒n─▒f tan─▒m─▒ yazd─▒─č─▒n─▒zda ve Python bunu ├žal─▒┼čt─▒rd─▒─č─▒nda, s─▒n─▒f nesnesini somutla┼čt─▒rmak i├žin bir metaclass kullan─▒r (s─▒rayla o s─▒n─▒f─▒n ├Ârneklerini somutla┼čt─▒rmak i├žin kullan─▒l─▒r).

├ľzel nesne ├Ârneklerinin davran─▒┼č ┼čeklini de─či┼čtirmek i├žin s─▒n─▒f tan─▒mlar─▒n─▒ kullanabildi─čimiz gibi, bir s─▒n─▒f nesnesinin davran─▒┼č ┼čeklini de─či┼čtirmek i├žin bir metaclass s─▒n─▒f─▒ tan─▒m─▒n─▒ kullanabiliriz.

Ne i├žin kullan─▒labilirler? G├Ânderen docs :

Metas─▒n─▒flar─▒n potansiyel kullan─▒mlar─▒ s─▒n─▒rs─▒zd─▒r. Ke┼čfedilen baz─▒ fikirler, g├╝nl├╝k kayd─▒, aray├╝z kontrol├╝, otomatik yetkilendirme, otomatik ├Âzellik olu┼čturma, proxy'ler, ├žer├ževeler ve otomatik kaynak kilitleme / senkronizasyonu i├žerir.

Bununla birlikte, genellikle gerekli olmad─▒k├ža, kullan─▒c─▒lar─▒n metas─▒n─▒flar─▒ kullanmaktan ka├ž─▒nmalar─▒ te┼čvik edilir.

Her s─▒n─▒f olu┼čturdu─čunuzda bir metaclass kullan─▒rs─▒n─▒z:

Bir s─▒n─▒f tan─▒m─▒ yazd─▒─č─▒n─▒zda, ├Ârne─čin, b├Âyle,

 class Foo(object): 
    'demo'
 

Bir s─▒n─▒f nesnesini ba┼člat─▒rs─▒n─▒z.

 >>> Foo
<class '__main__.Foo'>
>>> isinstance(Foo, type), isinstance(Foo, object)
(True, True)
 

─░┼člevsel olarak type uygun arg├╝manlarla ├ža─čr─▒ yapmak ve sonucu bu ismin bir de─či┼čkenine atamakla ayn─▒d─▒r :

 name = 'Foo'
bases = (object,)
namespace = {'__doc__': 'demo'}
Foo = type(name, bases, namespace)
 

Dikkat edin, baz─▒ ┼čeyler otomatik olarak __dict__ , yani ad alan─▒na eklenir :

 >>> Foo.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Foo' objects>, 
'__module__': '__main__', '__weakref__': <attribute '__weakref__' 
of 'Foo' objects>, '__doc__': 'demo'})
 

Her iki durumda da yaratt─▒─č─▒m─▒z nesnenin metaclass'─▒ type .

(S─▒n─▒f─▒n i├žeri─čine ili┼čkin bir not __dict__ : __module__ S─▒n─▒flar nerede tan─▒mland─▒klar─▒n─▒ bilmeleri gerekti─činden __dict__ ve __weakref__ orada tan─▒mlamad─▒─č─▒m─▒z i├žin de var __slots__ - Tan─▒mlarsak __slots__ ├Ârneklerde biraz yer kazanaca─č─▒z. ─░zin vermeyebilir __dict__ ve __weakref__ bunlar─▒ hari├ž tutarak ├ľrne─čin:

 >>> Baz = type('Bar', (object,), {'__doc__': 'demo', '__slots__': ()})
>>> Baz.__dict__
mappingproxy({'__doc__': 'demo', '__slots__': (), '__module__': '__main__'})
 

... ama dal─▒yorum.)

type Ba┼čka herhangi bir s─▒n─▒f tan─▒m─▒ gibi geni┼čletebiliriz :

─░┼čte __repr__ s─▒n─▒flar─▒n varsay─▒lan─▒ :

 >>> Foo
<class '__main__.Foo'>
 

Bir Python nesnesi yazarken varsay─▒lan olarak yapabilece─čimiz en de─čerli ┼čeylerden biri, ona iyi bir ┼čey sa─člamakt─▒r __repr__ . Arad─▒─č─▒m─▒zda , e┼čitlik i├žin bir test gerektiren bunun help(repr) i├žin iyi bir test oldu─čunu ├Â─čreniyoruz . Tip s─▒n─▒f─▒m─▒z─▒n ve s─▒n─▒f ├Ârneklerinin a┼ča─č─▒daki basit uygulamas─▒ , s─▒n─▒flar─▒n varsay─▒lan─▒ ├╝zerinde geli┼čebilecek bir g├Âsteri sa─člar : __repr__ obj == eval(repr(obj)) __repr__ __eq__ __repr__

 class Type(type):
    def __repr__(cls):
        """
        >>> Baz
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        >>> eval(repr(Baz))
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        """
        metaname = type(cls).__name__
        name = cls.__name__
        parents = ', '.join(b.__name__ for b in cls.__bases__)
        if parents:
            parents += ','
        namespace = ', '.join(': '.join(
          (repr(k), repr(v) if not isinstance(v, type) else v.__name__))
               for k, v in cls.__dict__.items())
        return '{0}(\'{1}\', ({2}), {{{3}}})'.format(metaname, name, parents, namespace)
    def __eq__(cls, other):
        """
        >>> Baz == eval(repr(Baz))
        True            
        """
        return (cls.__name__, cls.__bases__, cls.__dict__) == (
                other.__name__, other.__bases__, other.__dict__)
 

┼×imdi bu metaclass ile bir nesne yaratt─▒─č─▒m─▒zda __repr__ , komut sat─▒r─▒ndaki yank─▒ varsay─▒landan ├žok daha az ├žirkin bir g├Âr├╝┼č sa─člar:

 >>> class Bar(object): pass
>>> Baz = Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
>>> Baz
Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
 

__repr__ S─▒n─▒f ├Ârne─či i├žin iyi tan─▒mlanm─▒┼č bir tan─▒mla, kodumuzu hata ay─▒klama konusunda daha g├╝├žl├╝ bir yetene─če sahibiz. Bununla birlikte, ├žok daha fazla kontrol eval(repr(Class)) yap─▒lmas─▒ pek m├╝mk├╝n de─čildir (i┼člevler varsay─▒lanlar─▒ndan de─čerlendirmek olduk├ža imkans─▒z oldu─ču i├žin __repr__ ).

Beklenen kullan─▒m: __prepare__ bir ad alan─▒

├ľrne─čin, bir s─▒n─▒f─▒n y├Ântemlerinin hangi s─▒rayla olu┼čturuldu─čunu bilmek istiyorsak, s─▒n─▒f─▒n ad alan─▒ olarak s─▒ral─▒ bir dikte sa─člayabiliriz. Biz bu yapard─▒n __prepare__ hangi Python 3'te uygulan─▒rsa s─▒n─▒f i├žin ad dicti d├Ând├╝r├╝r :

 from collections import OrderedDict

class OrderedType(Type):
    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        return OrderedDict()
    def __new__(cls, name, bases, namespace, **kwargs):
        result = Type.__new__(cls, name, bases, dict(namespace))
        result.members = tuple(namespace)
        return result
 

Ve kullan─▒m:

 class OrderedMethodsObject(object, metaclass=OrderedType):
    def method1(self): pass
    def method2(self): pass
    def method3(self): pass
    def method4(self): pass
 

Ve ┼čimdi, bu y├Ântemlerin (ve di─čer s─▒n─▒f niteliklerinin) yarat─▒lma d├╝zeninin bir kayd─▒na sahibiz:

 >>> OrderedMethodsObject.members
('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4')
 

Not, bu ├Ârnek dok├╝mantasyondan uyarlanm─▒┼čt─▒r - standart k├╝t├╝phanedeki yeni numaraland─▒rma bunu yapar.

├ľyleyse yapt─▒─č─▒m─▒z ┼čey, bir s─▒n─▒f olu┼čturarak bir metaclass ├Ârne─čini ba┼člatmakt─▒. Ayr─▒ca metaclass'─▒ di─čer s─▒n─▒flardaki gibi ele alabiliriz. Bir y├Ântem ├ž├Âz├╝mleme s─▒ras─▒ var:

 >>> inspect.getmro(OrderedType)
(<class '__main__.OrderedType'>, <class '__main__.Type'>, <class 'type'>, <class 'object'>)
 

Ve yakla┼č─▒k olarak do─čru vard─▒r repr (i┼člevlerimizi temsil edecek bir yol bulamazsak, art─▒k de─čerlendiremeyiz.):

 >>> OrderedMethodsObject
OrderedType('OrderedMethodsObject', (object,), {'method1': <function OrderedMethodsObject.method1 at 0x0000000002DB01E0>, 'members': ('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4'), 'method3': <function OrderedMet
hodsObject.method3 at 0x0000000002DB02F0>, 'method2': <function OrderedMethodsObject.method2 at 0x0000000002DB0268>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'OrderedMethodsObject' objects>, '__doc__': None, '__d
ict__': <attribute '__dict__' of 'OrderedMethodsObject' objects>, 'method4': <function OrderedMethodsObject.method4 at 0x0000000002DB0378>})
 

97







Python 3 g├╝ncellemesi

Bir metaclass'ta (bu noktada) iki anahtar y├Ântem vard─▒r:

  • __prepare__ , ve
  • __new__

__prepare__ OrderedDict s─▒n─▒f olu┼čturulurken ad alan─▒ olarak kullan─▒lacak ├Âzel bir e┼čleme (├Ârne─čin bir ) sa─člaman─▒za olanak tan─▒r . Se├žti─činiz herhangi bir ad alan─▒n─▒n bir ├Ârne─čini d├Ând├╝rmelisiniz. E─čer uygulam─▒yorsan─▒z __prepare__ normal dict kullan─▒l─▒r.

__new__ final s─▒n─▒f─▒n─▒n as─▒l yarat─▒lmas─▒ndan / de─či┼čtirilmesinden sorumludur.

├ç─▒plak kemikler, hi├žbir ┼čey yapmadan ekstra bir metaclass istiyorum:

 class Meta(type):

    def __prepare__(metaclass, cls, bases):
        return dict()

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)
 

Basit bir ├Ârnek:

Baz─▒ basit do─črulama kodunun ├Âzellikleriniz ├╝zerinde ├žal─▒┼čmas─▒n─▒ istedi─činizi varsayal─▒m - sanki her zaman bir int ya da a olmal─▒ str . Bir metaclass olmadan, s─▒n─▒f─▒n─▒z ┼čunun gibi g├Âr├╝n├╝r:

 class Person:
    weight = ValidateType('weight', int)
    age = ValidateType('age', int)
    name = ValidateType('name', str)
 

G├Ârebildi─činiz gibi, ├Âzniteli─čin ad─▒n─▒ iki kez tekrarlaman─▒z gerekir. Bu tahri┼č edici b├Âcek ile birlikte yaz─▒m hatalar─▒ m├╝mk├╝n k─▒lar.

Basit bir metaclass bu sorunu ├ž├Âzebilir:

 class Person(metaclass=Validator):
    weight = ValidateType(int)
    age = ValidateType(int)
    name = ValidateType(str)
 

Metaclass'─▒n neye benzeyece─či budur (gerekmedi─činden kullanm─▒yorsunuz __prepare__ ):

 class Validator(type):
    def __new__(metacls, cls, bases, clsdict):
        # search clsdict looking for ValidateType descriptors
        for name, attr in clsdict.items():
            if isinstance(attr, ValidateType):
                attr.name = name
                attr.attr = '_' + name
        # create final class and return it
        return super().__new__(metacls, cls, bases, clsdict)
 

Bir ├Ârnek ├žal─▒┼čma:

 p = Person()
p.weight = 9
print(p.weight)
p.weight = '9'
 

├╝retir:

 9
Traceback (most recent call last):
  File "simple_meta.py", line 36, in <module>
    p.weight = '9'
  File "simple_meta.py", line 24, in __set__
    (self.name, self.type, value))
TypeError: weight must be of type(s) <class 'int'> (got '9')
 

Not : Bu ├Ârnek, bir s─▒n─▒f dekorat├Ârle de yap─▒labilecek kadar basittir, ancak muhtemelen ger├žek bir metaclass daha fazlas─▒n─▒ yapard─▒.

Ba┼čvuru i├žin 'ValidateType' s─▒n─▒f─▒:

 class ValidateType:
    def __init__(self, type):
        self.name = None  # will be set by metaclass
        self.attr = None  # will be set by metaclass
        self.type = type
    def __get__(self, inst, cls):
        if inst is None:
            return self
        else:
            return inst.__dict__[self.attr]
    def __set__(self, inst, value):
        if not isinstance(value, self.type):
            raise TypeError('%s must be of type(s) %s (got %r)' %
                    (self.name, self.type, value))
        else:
            inst.__dict__[self.attr] = value
 

71







__call__() S─▒n─▒f ├Ârne─či olu┼čtururken bir metaclass ' y├Ânteminin rol├╝

Python programlamay─▒ birka├ž aydan daha uzun bir s├╝re boyunca yapt─▒ysan─▒z, sonunda ┼čuna benzer bir kod yazman─▒z gerekir:

 # define a class
class SomeClass(object):
    # ...
    # some definition here ...
    # ...

# create an instance of it
instance = SomeClass()

# then call the object as if it's a function
result = instance('foo', 'bar')
 

Sonuncusu, __call__() s─▒n─▒fa sihirli metodu uygulad─▒─č─▒n─▒zda m├╝mk├╝nd├╝r .

 class SomeClass(object):
    # ...
    # some definition here ...
    # ...

    def __call__(self, foo, bar):
        return bar + foo
 

__call__() Bir s─▒n─▒f─▒n bir ├Ârne─či, bir ├ža─čr─▒labilir olarak kullan─▒ld─▒─č─▒ zaman, y├Ântem, ├ža─čr─▒l─▒r. Ancak ├Ânceki cevaplardan g├Ârd├╝─č├╝m├╝z gibi, s─▒n─▒f─▒n kendisi bir metaclass ├Ârne─čidir, bu y├╝zden s─▒n─▒f─▒ ├ža─čr─▒labilir olarak kulland─▒─č─▒m─▒zda (yani bir ├Ârne─čini olu┼čturdu─čumuzda) asl─▒nda metaclass __call__() y├Ântemini ├ža─č─▒r─▒yoruz . Bu noktada ├žo─ču Python programc─▒s─▒n─▒n kafas─▒ biraz kar─▒┼č─▒k, ├ž├╝nk├╝ bunun gibi bir ├Ârnek olu┼čtururken y├Ântemini instance = SomeClass() ├ža─č─▒rd─▒─č─▒n─▒z─▒ s├Âylemi┼člerdi __init__() . Biraz daha derine kaz─▒lm─▒┼č ettik kim Baz─▒ ├Ânce biliyoruz __init__() var __new__() . Bug├╝n, ba┼čka bir do─čruluk katman─▒ ortaya ├ž─▒k─▒yor, __new__() metaclass olmadan ├Ânce __call__() .

Y├Ântem ├ža─čr─▒ zincirini, ├Âzellikle bir s─▒n─▒f ├Ârne─či olu┼čturma perspektifinden inceleyelim.

Bu, bir ├Ârnek olu┼čturulmadan ├Ânceki an─▒ ve geri d├Ând├╝rmek ├╝zere oldu─ču an─▒ kaydeden bir metaclass.

 class Meta_1(type):
    def __call__(cls):
        print "Meta_1.__call__() before creating an instance of ", cls
        instance = super(Meta_1, cls).__call__()
        print "Meta_1.__call__() about to return instance."
        return instance
 

Bu, bu metaclass'─▒ kullanan bir s─▒n─▒ft─▒r

 class Class_1(object):

    __metaclass__ = Meta_1

    def __new__(cls):
        print "Class_1.__new__() before creating an instance."
        instance = super(Class_1, cls).__new__(cls)
        print "Class_1.__new__() about to return instance."
        return instance

    def __init__(self):
        print "entering Class_1.__init__() for instance initialization."
        super(Class_1,self).__init__()
        print "exiting Class_1.__init__()."
 

Ve ┼čimdi bir ├Ârne─čini olu┼čtural─▒m Class_1

 instance = Class_1()
# Meta_1.__call__() before creating an instance of <class '__main__.Class_1'>.
# Class_1.__new__() before creating an instance.
# Class_1.__new__() about to return instance.
# entering Class_1.__init__() for instance initialization.
# exiting Class_1.__init__().
# Meta_1.__call__() about to return instance.
 

Yukar─▒daki kodun, g├Ârevleri kaydetmekten ba┼čka bir ┼čey yapmad─▒─č─▒n─▒ g├Âzlemleyin. Her y├Ântem, as─▒l i┼či ebeveyni i├žin g├Ârevlendirerek varsay─▒lan davran─▒┼č─▒ korur. Yana type oldu─čunu Meta_1 '─▒n ├╝st s─▒n─▒f ( type varsay─▒lan ebeveyn metaclass olmak ├╝zere) ve yukar─▒daki ├ž─▒k─▒┼č─▒n sipari┼č dizisini g├Âz ├Ân├╝ne al─▒nd─▒─č─▒nda art─▒k s├Âzde uygulamas─▒ ne olaca─č─▒n─▒ bir ipucu var type.__call__() :

 class type:
    def __call__(cls, *args, **kwarg):

        # ... maybe a few things done to cls here

        # then we call __new__() on the class to create an instance
        instance = cls.__new__(cls, *args, **kwargs)

        # ... maybe a few things done to the instance here

        # then we initialize the instance with its __init__() method
        instance.__init__(*args, **kwargs)

        # ... maybe a few more things done to instance here

        # then we return it
        return instance
 

Metaclass ' __call__() y├Ânteminin ilk ad─▒ verilen y├Ântem oldu─čunu g├Ârebiliriz . Daha sonra, ├Ârne─čin olu┼čturulmas─▒n─▒ s─▒n─▒f─▒n __new__() y├Ântemine ve ├Ârneklemenin ilk harfine devreder __init__() . Ayn─▒ zamanda nihayetinde ├Ârne─či geri veren de o.

├ťst├╝ndeki Metaclass' oldu─čunu kaynaklan─▒yor itibaren __call__() de edip etmeme ├ža─čr─▒s─▒ karar i├žin f─▒rsat verilir Class_1.__new__() veya Class_1.__init__() sonunda yap─▒lacakt─▒r. Uygulamas─▒ boyunca bu y├Ântemlerden herhangi biriyle dokunulmam─▒┼č bir nesneyi geri getirebilirdi. ├ľrne─čin, bu yakla┼č─▒m─▒ singleton modeline uygulay─▒n:

 class Meta_2(type):
    singletons = {}

    def __call__(cls, *args, **kwargs):
        if cls in Meta_2.singletons:
            # we return the only instance and skip a call to __new__()
            # and __init__()
            print ("{} singleton returning from Meta_2.__call__(), "
                   "skipping creation of new instance.".format(cls))
            return Meta_2.singletons[cls]

        # else if the singleton isn't present we proceed as usual
        print "Meta_2.__call__() before creating an instance."
        instance = super(Meta_2, cls).__call__(*args, **kwargs)
        Meta_2.singletons[cls] = instance
        print "Meta_2.__call__() returning new instance."
        return instance

class Class_2(object):

    __metaclass__ = Meta_2

    def __new__(cls, *args, **kwargs):
        print "Class_2.__new__() before creating instance."
        instance = super(Class_2, cls).__new__(cls)
        print "Class_2.__new__() returning instance."
        return instance

    def __init__(self, *args, **kwargs):
        print "entering Class_2.__init__() for initialization."
        super(Class_2, self).__init__()
        print "exiting Class_2.__init__()."
 

Bir t├╝r nesneyi art arda olu┼čturmaya ├žal─▒┼č─▒rken ne oldu─čunu g├Ârelim. Class_2

 a = Class_2()
# Meta_2.__call__() before creating an instance.
# Class_2.__new__() before creating instance.
# Class_2.__new__() returning instance.
# entering Class_2.__init__() for initialization.
# exiting Class_2.__init__().
# Meta_2.__call__() returning new instance.

b = Class_2()
# <class '__main__.Class_2'> singleton returning from Meta_2.__call__(), skipping creation of new instance.

c = Class_2()
# <class '__main__.Class_2'> singleton returning from Meta_2.__call__(), skipping creation of new instance.

a is b is c # True
 

62







Bir metaclass, ba┼čka bir s─▒n─▒f─▒n nas─▒l (baz─▒) olu┼čturulmas─▒ gerekti─čini s├Âyleyen bir s─▒n─▒ft─▒r.

Bu, metaclass'─▒ problemime bir ├ž├Âz├╝m olarak g├Ârd├╝─č├╝mde: Ger├žekten karma┼č─▒k bir problemim vard─▒, muhtemelen farkl─▒ ┼čekilde ├ž├Âz├╝lebilirdi, ancak bir metaclass kullanarak ├ž├Âzmeyi se├žtim. Karma┼č─▒kl─▒k nedeniyle, mod├╝ldeki yorumlar─▒n yaz─▒lan kod miktar─▒n─▒ a┼čt─▒─č─▒ yerlerde yazd─▒─č─▒m az say─▒daki mod├╝lden biri. ─░┼čte burada...

 #!/usr/bin/env python

# Copyright (C) 2013-2014 Craig Phillips.  All rights reserved.

# This requires some explaining.  The point of this metaclass excercise is to
# create a static abstract class that is in one way or another, dormant until
# queried.  I experimented with creating a singlton on import, but that did
# not quite behave how I wanted it to.  See now here, we are creating a class
# called GsyncOptions, that on import, will do nothing except state that its
# class creator is GsyncOptionsType.  This means, docopt doesn't parse any
# of the help document, nor does it start processing command line options.
# So importing this module becomes really efficient.  The complicated bit
# comes from requiring the GsyncOptions class to be static.  By that, I mean
# any property on it, may or may not exist, since they are not statically
# defined; so I can't simply just define the class with a whole bunch of
# properties that are @property @staticmethods.
#
# So here's how it works:
#
# Executing 'from libgsync.options import GsyncOptions' does nothing more
# than load up this module, define the Type and the Class and import them
# into the callers namespace.  Simple.
#
# Invoking 'GsyncOptions.debug' for the first time, or any other property
# causes the __metaclass__ __getattr__ method to be called, since the class
# is not instantiated as a class instance yet.  The __getattr__ method on
# the type then initialises the class (GsyncOptions) via the __initialiseClass
# method.  This is the first and only time the class will actually have its
# dictionary statically populated.  The docopt module is invoked to parse the
# usage document and generate command line options from it.  These are then
# paired with their defaults and what's in sys.argv.  After all that, we
# setup some dynamic properties that could not be defined by their name in
# the usage, before everything is then transplanted onto the actual class
# object (or static class GsyncOptions).
#
# Another piece of magic, is to allow command line options to be set in
# in their native form and be translated into argparse style properties.
#
# Finally, the GsyncListOptions class is actually where the options are
# stored.  This only acts as a mechanism for storing options as lists, to
# allow aggregation of duplicate options or options that can be specified
# multiple times.  The __getattr__ call hides this by default, returning the
# last item in a property's list.  However, if the entire list is required,
# calling the 'list()' method on the GsyncOptions class, returns a reference
# to the GsyncListOptions class, which contains all of the same properties
# but as lists and without the duplication of having them as both lists and
# static singlton values.
#
# So this actually means that GsyncOptions is actually a static proxy class...
#
# ...And all this is neatly hidden within a closure for safe keeping.
def GetGsyncOptionsType():
    class GsyncListOptions(object):
        __initialised = False

    class GsyncOptionsType(type):
        def __initialiseClass(cls):
            if GsyncListOptions._GsyncListOptions__initialised: return

            from docopt import docopt
            from libgsync.options import doc
            from libgsync import __version__

            options = docopt(
                doc.__doc__ % __version__,
                version = __version__,
                options_first = True
            )

            paths = options.pop('<path>', None)
            setattr(cls, "destination_path", paths.pop() if paths else None)
            setattr(cls, "source_paths", paths)
            setattr(cls, "options", options)

            for k, v in options.iteritems():
                setattr(cls, k, v)

            GsyncListOptions._GsyncListOptions__initialised = True

        def list(cls):
            return GsyncListOptions

        def __getattr__(cls, name):
            cls.__initialiseClass()
            return getattr(GsyncListOptions, name)[-1]

        def __setattr__(cls, name, value):
            # Substitut option names: --an-option-name for an_option_name
            import re
            name = re.sub(r'^__', "", re.sub(r'-', "_", name))
            listvalue = []

            # Ensure value is converted to a list type for GsyncListOptions
            if isinstance(value, list):
                if value:
                    listvalue = [] + value
                else:
                    listvalue = [ None ]
            else:
                listvalue = [ value ]

            type.__setattr__(GsyncListOptions, name, listvalue)

    # Cleanup this module to prevent tinkering.
    import sys
    module = sys.modules[__name__]
    del module.__dict__['GetGsyncOptionsType']

    return GsyncOptionsType

# Our singlton abstract proxy class.
class GsyncOptions(object):
    __metaclass__ = GetGsyncOptionsType()
 

52







type asl─▒nda bir metaclass - ba┼čka s─▒n─▒flar yaratan bir s─▒n─▒f. ├ço─ču metaclass alt s─▒n─▒flard─▒r type . metaclass Ald─▒─č─▒nda new ilk arg├╝man olarak s─▒n─▒f ve a┼ča─č─▒da belirtilen ayr─▒nt─▒lar─▒ ile s─▒n─▒f nesnesi eri┼čim sa─člar:

 >>> class MetaClass(type):
...     def __init__(cls, name, bases, attrs):
...         print ('class name: %s' %name )
...         print ('Defining class %s' %cls)
...         print('Bases %s: ' %bases)
...         print('Attributes')
...         for (name, value) in attrs.items():
...             print ('%s :%r' %(name, value))
... 

>>> class NewClass(object, metaclass=MetaClass):
...    get_choch='dairy'
... 
class name: NewClass
Bases <class 'object'>: 
Defining class <class 'NewClass'>
get_choch :'dairy'
__module__ :'builtins'
__qualname__ :'NewClass'
 

Note:

S─▒n─▒f─▒n hi├žbir zaman somutla┼čt─▒r─▒lmad─▒─č─▒na dikkat edin; s─▒n─▒f─▒ yaratman─▒n basit eylemi metaclass ,.


37







Tl; dr s├╝r├╝m├╝

type(obj) Fonksiyon size bir nesnenin t├╝r├╝n├╝ al─▒r.

type() Bir s─▒n─▒f─▒n onun oldu─ču metaclass .

Bir metaclass kullanmak i├žin:

 class Foo(object):
    __metaclass__ = MyMetaClass
 

34







Python s─▒n─▒flar─▒ kendileridir - ├Ârne─čin meta s─▒n─▒flar─▒n─▒n nesneleridir.

S─▒n─▒flar─▒ ┼ču ┼čekilde belirlerken uygulanan varsay─▒lan metaclass:

 class foo:
    ...
 

meta s─▒n─▒f─▒, baz─▒ kurallar─▒ t├╝m s─▒n─▒flara uygulamak i├žin kullan─▒l─▒r. ├ľrne─čin, bir veritaban─▒na eri┼čmek i├žin bir ORM olu┼čturdu─čunuzu ve her tablonun kay─▒tlar─▒n─▒n o tabla ile e┼členen bir s─▒n─▒fta olmas─▒n─▒ istedi─činiz (alanlar, i┼č kurallar─▒, vb. ├Ârne─čin, t├╝m tablolardaki t├╝m kay─▒t s─▒n─▒flar─▒ taraf─▒ndan payla┼č─▒lan ba─člant─▒ havuzu mant─▒─č─▒. Di─čer bir kullan─▒m, birden fazla kay─▒t s─▒n─▒f─▒n─▒ i├žeren yabanc─▒ anahtarlar─▒ desteklemek i├žin mant─▒kt─▒r.

metaclass'─▒ tan─▒mlad─▒─č─▒n─▒zda, alt s─▒n─▒f─▒ yazars─▒n─▒z ve mant─▒─č─▒n─▒z─▒ eklemek i├žin a┼ča─č─▒daki sihirli y├Ântemleri ge├žersiz k─▒labilirsiniz.

 class somemeta(type):
    __new__(mcs, name, bases, clsdict):
      """
  mcs: is the base metaclass, in this case type.
  name: name of the new class, as provided by the user.
  bases: tuple of base classes 
  clsdict: a dictionary containing all methods and attributes defined on class

  you must return a class object by invoking the __new__ constructor on the base metaclass. 
 ie: 
    return type.__call__(mcs, name, bases, clsdict).

  in the following case:

  class foo(baseclass):
        __metaclass__ = somemeta

  an_attr = 12

  def bar(self):
      ...

  @classmethod
  def foo(cls):
      ...

      arguments would be : ( somemeta, "foo", (baseclass, baseofbase,..., object), {"an_attr":12, "bar": <function>, "foo": <bound class method>}

      you can modify any of these values before passing on to type
      """
      return type.__call__(mcs, name, bases, clsdict)


    def __init__(self, name, bases, clsdict):
      """ 
      called after type has been created. unlike in standard classes, __init__ method cannot modify the instance (cls) - and should be used for class validaton.
      """
      pass


    def __prepare__():
        """
        returns a dict or something that can be used as a namespace.
        the type will then attach methods and attributes from class definition to it.

        call order :

        somemeta.__new__ ->  type.__new__ -> type.__init__ -> somemeta.__init__ 
        """
        return dict()

    def mymethod(cls):
        """ works like a classmethod, but for class objects. Also, my method will not be visible to instances of cls.
        """
        pass
 

Her neyse, bu ikisi en s─▒k kullan─▒lan kancalard─▒r. metaclassing g├╝├žl├╝d├╝r ve yukar─▒da metaclassing kullan─▒mlar─▒n─▒n hi├žbir yerinde ve ayr─▒nt─▒l─▒ bir listesi yoktur.


23







Type () i┼člevi bir nesnenin t├╝r├╝n├╝ d├Ând├╝r├╝r veya yeni bir t├╝r olu┼čturur,

├Ârne─čin, type () i┼čleviyle bir Hi s─▒n─▒f─▒ olu┼čturabiliriz ve bu ┼čekilde Hi (object) s─▒n─▒f─▒yla kullanmaya gerek yoktur:

 def func(self, name='mike'):
    print('Hi, %s.' % name)

Hi = type('Hi', (object,), dict(hi=func))
h = Hi()
h.hi()
Hi, mike.

type(Hi)
type

type(h)
__main__.Hi
 

Dinamik olarak s─▒n─▒flar olu┼čturmak i├žin type () kullanmaya ek olarak, s─▒n─▒f olu┼čturma davran─▒┼č─▒n─▒ kontrol edebilir ve metaclass kullanabilirsiniz.

Python nesne modeline g├Âre, s─▒n─▒f nesnedir, bu y├╝zden s─▒n─▒f ba┼čka bir s─▒n─▒f─▒n ├Ârne─či olmal─▒d─▒r. Varsay─▒lan olarak, bir Python s─▒n─▒f─▒, type s─▒n─▒f─▒n─▒n bir ├Ârne─čidir. Di─čer bir deyi┼čle t├╝r, yerle┼čik s─▒n─▒flar─▒n ├žo─čunun metaclass'─▒ ve kullan─▒c─▒ tan─▒ml─▒ s─▒n─▒flar─▒n metaclass'lar─▒d─▒r.

 class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

class CustomList(list, metaclass=ListMetaclass):
    pass

lst = CustomList()
lst.add('custom_list_1')
lst.add('custom_list_2')

lst
['custom_list_1', 'custom_list_2']
 

Metaclass'ta anahtar kelime arg├╝manlar─▒n─▒ iletti─čimizde Magic etkili olacak, Python yorumlay─▒c─▒s─▒n─▒ ListMetaclass arac─▒l─▒─č─▒yla CustomList olu┼čturmak i├žin g├Âsterir. new (), bu noktada, ├Ârne─čin s─▒n─▒f tan─▒m─▒n─▒ de─či┼čtirebilir ve yeni bir y├Ântem ekleyebilir ve sonra de─či┼čtirilmi┼č tan─▒m─▒ geri d├Ând├╝rebiliriz.


18







Yay─▒nlanan cevaplara ek olarak, metaclass bir s─▒n─▒f─▒n davran─▒┼č─▒n─▒ tan─▒mlad─▒─č─▒n─▒ s├Âyleyebilirim . B├Âylece, a├ž─▒k├ža metaclass'─▒n─▒z─▒ ayarlayabilirsiniz. Python ne zaman bir anahtar kelime al─▒rsa, class o zaman aramaya ba┼člar metaclass . Bulunmazsa, varsay─▒lan metaclass t├╝r├╝ s─▒n─▒f─▒n nesnesini olu┼čturmak i├žin kullan─▒l─▒r. __metaclass__ ├ľzniteli─či kullanarak, metaclass s─▒n─▒f─▒n─▒z─▒ ayarlayabilirsiniz :

 class MyClass:
   __metaclass__ = type
   # write here other method
   # write here one more method

print(MyClass.__metaclass__)
 

Bu ┼čekilde ├ž─▒kt─▒ ├╝retecek:

 class 'type'
 

Ve elbette, metaclass s─▒n─▒f─▒n─▒z─▒ kullanarak olu┼čturulan herhangi bir s─▒n─▒f─▒n davran─▒┼č─▒n─▒ tan─▒mlamak i├žin kendiniz de olu┼čturabilirsiniz .

Bunu yapmak i├žin, varsay─▒lan metaclass t├╝r s─▒n─▒f─▒n─▒z ana oldu─ču i├žin miras al─▒nmal─▒d─▒r metaclass :

 class MyMetaClass(type):
   __metaclass__ = type
   # you can write here any behaviour you want

class MyTestClass:
   __metaclass__ = MyMetaClass

Obj = MyTestClass()
print(Obj.__metaclass__)
print(MyMetaClass.__metaclass__)
 

Çıktı:

 class '__main__.MyMetaClass'
class 'type'
 

8







Nesne y├Ânelimli programlamada, bir metaclass, ├Ârnekleri s─▒n─▒f olan bir s─▒n─▒ft─▒r. S─▒radan bir s─▒n─▒f, belirli nesnelerin davran─▒┼č─▒n─▒ tan─▒mlad─▒─č─▒ gibi, bir metaclass, belirli s─▒n─▒f─▒n davran─▒┼č─▒n─▒ ve bunlar─▒n ├Ârneklerini tan─▒mlar. Metaclass terimi, sadece s─▒n─▒f olu┼čturmak i├žin kullan─▒lan bir ┼čey anlam─▒na gelir. Ba┼čka bir deyi┼čle, bir s─▒n─▒f─▒n s─▒n─▒f─▒d─▒r. Metaclass s─▒n─▒f─▒ olu┼čturmak i├žin kullan─▒l─▒r, b├Âylece nesne bir s─▒n─▒f─▒n ├Ârne─či oldu─ču gibi, s─▒n─▒f da bir metaclass ├Ârne─čidir. Python s─▒n─▒flar─▒nda ayr─▒ca nesneler olarak kabul edilir.


0



─░lgili yay─▒nlar


JQuery'deki s─▒ralar nelerdir?

.NET'teki ├Âzellikler nelerdir?

Baz─▒ iyi Python ORM ├ž├Âz├╝mleri nelerdir? [kapal─▒]

.NET'te 'kapan─▒┼člar' nedir?

Programlamada fikst├╝rler nelerdir?

Java G├╝nl├╝─č├╝ ├žer├ževelerinde belirte├žler nelerdir ve bunlar─▒ kullanmak i├žin neden nedir?

C++ 20'deki koroinler nelerdir?

C# 'kapan─▒┼člar─▒' nelerdir? [├žift]

Python'daki deque'ler nas─▒l uygulan─▒r ve bunlar listeden ne zaman daha k├Ât├╝d├╝r?

G├Âr├╝nt├╝ i┼člemede kilit noktalar nelerdir?

Etiketle ilgili di─čer sorular [python]


BehaviorSubject vs G├Âzlenebilir mi?

JQuery ile ka├ž─▒┼č anahtar─▒ i├žin hangi anahtar kodu

Es6 s─▒n─▒flar─▒ kullan─▒l─▒rken React'te ÔÇťsuper ()ÔÇŁ ve ÔÇťsuper (props)ÔÇŁ aras─▒ndaki fark nedir?

Subversion'daki kodumuzun eski bir s├╝r├╝m├╝ne nas─▒l geri d├Ânerim?

Sublime Text'deki iki dosyan─▒n i├žeri─čini kar┼č─▒la┼čt─▒rma

Android'de programl─▒ bir g├Âr├╝nt├╝ g├Âr├╝nt├╝s├╝ i├žin renk tonu nas─▒l ayarlan─▒r?

Node.js genel olarak 10.000 e┼čzamanl─▒ iste─či nas─▒l ele al─▒r?

GO'nun SQL Server Management Studio ve Transact SQL'deki kullan─▒m─▒ nedir?

├ľzyinelemeli dosya listesi i├žin derinli─či nas─▒l s─▒n─▒rlan─▒r?

Slayt yukar─▒ / a┼ča─č─▒ animasyonuyla bir G├Âr├╝n├╝m g├Âsterme ve gizleme