SORU
26 HAZİRAN 2013, ÇARŞAMBA


Nasıl @özelliğini dekoratör iş yapar?

Yerleşik fonksiyonunu anlamak istiyorum property çalışır. Benim için kafa karıştırıcı bölümü property bir dekoratör, bir işlevi dekorasyon için argümanlar yok iken de olabilir.

Bu örnek documentation dan:

class C(object):
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

property'nın bağımsız değişkenlerigetx, setx, delx ve doktor bir dize.

Aşağıdaki kod property dekoratör olarak kullanılır. Amaç x işlevi vardır, ama yukarıdaki kod içinde bağımsız bir nesne işlevi için yer yoktur.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

Ve nasıl x.setter x.deleter dekoratörler yarattı? Kafam karıştı.

CEVAP
26 HAZİRAN 2013, ÇARŞAMBA


property() işlev bir özel descriptor object:

>>> property()
<property object at 0x10ff07940>

Bu nesneekstrayöntem:

>>> property().getter
<built-in method getter of property object at 0x10ff07998>
>>> property().setter
<built-in method setter of property object at 0x10ff07940>
>>> property().deleter
<built-in method deleter of property object at 0x10ff07998>

Bu dekoratör olarak hareket ederlerçok. Onlar yeni bir özellik bir nesne döndürür:

>>> property().getter(None)
<property object at 0x10ff079f0>

bu işlevleri yerine yaşlı bir nesne, ama bir kopyasıdır.

@decorator sözdizimi sadece sözdizimsel şeker olduğunu unutmayın; sözdizimi:

@property
def foo(self): return self._foo

gerçekten aynı şeyi ifade ediyor

def foo(self): return self._foo
foo = property(foo)

foo işlevi gördük yukarıda özel bir nesne olan property(foo) tarafından değiştirilir. Ne yaptığını kullandığınızda @foo.setter(), bir kopyasını verir, yukarıda gösterdim property().setter bu yöntemi çağırınaynı özellikayarlayıcı işlevi dekore yöntemi ile değiştirilir , ama.

Şu sıra aynı zamanda tam bir özellik, bu dekoratör yöntemleri kullanarak oluşturur.

İlk olarak, bazı işlevler ve sadece bir alıcı ile property bir nesne oluşturuyoruz:

>>> def getter(self): print 'Get!'
... 
>>> def setter(self, value): print 'Set to {!r}!'.format(value)
... 
>>> def deleter(self): print 'Delete!'
... 
>>> prop = property(getter)
>>> prop.fget is getter
True
>>> prop.fset is None
True
>>> prop.fdel is None
True

Önümüzdeki bir pasör eklemek için .setter() yöntemini kullanırız:

>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True

Son .deleter() yöntemi ile deleter ekliyoruz:

>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True

Son ama en az değil, property nesne gibi çalışır descriptor object var .__get__(), .__set__() .__delete__() yöntemler için kanca içine örnek öznitelik alma, ayarlama ve silme:

>>> class Foo(object): pass
... 
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!

Tanımlayıcı Nasıl Yapılır property() türü pure python sample implementation içerir:

class Property(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BurnedInDotCom

    BurnedInDotC

    3 NİSAN 2010
  • Missouri Star Quilt Company

    Missouri Sta

    18 ŞUBAT 2009
  • TSE

    TSE

    12 Kasım 2012