Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

dyskryptory

19 views
Skip to first unread message

ak3031884

unread,
Nov 27, 2009, 4:21:33 PM11/27/09
to
Witam,
zabieram się za temat dyskryptorów po raz ......no dużo tego było ale
tym razem powiedziałem sobie że nie odpuszcze bo nie rozumiem całego
stanu rzeczy z dyskryptorami po co je wymyślili dojście do składowych
klasy w pythonnie możemy uzyskać w bardzo prosyt sposób prawda

clsss myClass():
def __init__(self, a, b):
self.a = a
self.b = b
return

my = Class()
my.a =1
my.b=2

czysyt ładny kod, dojście jest a jeżeli chcemy to zakapsułkować to
zawsz możemy zmienne ustawić na
self.__a będzie to zmienna praywatna której nie zmodyfikujemy
z dyskryptorami będzie to wyglądało tak

class myClass(object):
def __init__(self, self, a, b):
self.a = a
self.b = b

def __get__(self, obj, objtype):
return self.a

def __set__(self, obj, val):
self.a = a

2 klasa nie wiem czy dobrze napisana bo nie rozumiem tego ale to koło
tego ma wyglądać.
Tak czy inaczej więcej pisania, zagmatwane, moim skromnym zdaniem nie
bardzo czytelne,
wytłumaczcie mi co w tym takiego dobrego iż jest to wprowadzane do
każdego języka programowania.


Daniel Mróz

unread,
Nov 27, 2009, 5:40:11 PM11/27/09
to
On 27.11.2009, ak3031884 <ak30...@gmail.com> wrote:
> zabieram się za temat dyskryptorów po raz ......no dużo tego było ale
dys.... co?

> class myClass(object):
> def __init__(self, self, a, b):
> self.a = a
> self.b = b
>
> def __get__(self, obj, objtype):
> return self.a
>
> def __set__(self, obj, val):
> self.a = a
>
> 2 klasa nie wiem czy dobrze napisana bo nie rozumiem tego ale to koło
> tego ma wyglądać.
> Tak czy inaczej więcej pisania, zagmatwane, moim skromnym zdaniem nie
> bardzo czytelne,
> wytłumaczcie mi co w tym takiego dobrego iż jest to wprowadzane do
> każdego języka programowania.

Nikt Ci nie każe używać __get__/__set__, możesz przypisywać/pobierać
wartości bez nich. Jeśli chcesz jednak np. dodać sprawdzanie typu (z rzucaniem
stosownego wyjątku), te metody pozwalają Ci na zrobienie tego niejawnie.
W ten sposób klasa sama się zatroszczy o siebie, a Ty nie będziesz musiał
używać javowych potworków typu:

obj.setA(value)

Oczywiście można je wykorzystać także do innych zabaw. Co Ci tylko
przyjdzie na myśl. Masz mechanizm, który *możesz* wykorzystać, ale
*nie musisz*.


Pozdrawiam
Beorn

--
Daniel 'Beorn' Mróz <be...@alpha.pl> http://127.0.0.1/beorn
[GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---]
[O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*]
[ r++ y+ ]

Daniel Mróz

unread,
Nov 27, 2009, 6:47:33 PM11/27/09
to
On 27.11.2009, Daniel Mróz <be...@alpha.pl> wrote:
> Nikt Ci nie każe używać __get__/__set__, możesz przypisywać/pobierać
> wartości bez nich. Jeśli chcesz jednak np. dodać sprawdzanie typu (z rzucaniem
> stosownego wyjątku), te metody pozwalają Ci na zrobienie tego niejawnie.
> W ten sposób klasa sama się zatroszczy o siebie, a Ty nie będziesz musiał
> używać javowych potworków typu:
>
> obj.setA(value)
>
> Oczywiście można je wykorzystać także do innych zabaw. Co Ci tylko
> przyjdzie na myśl. Masz mechanizm, który *możesz* wykorzystać, ale
> *nie musisz*.
OK, po czyms takim nawet ja nie byłbym przekonany co do potęgi tego
mechanizmu, więc wytłumaczę jeszcze raz na przykładzie (z życia
wziętym).
Wyobraź sobie, że piszesz aplikację operująca na bezklasowych
zakresach adresów IP. Naturalnym jest, że w tym celu tworzy się klasę
(pythonową) zawierającą m.in. atrybuty początku i końca zakresu.
Taką klasę w wersji podstawowej każdy jest w stanie zbudowac sobie
w myślach bez większego wysiłku. Są jednak cztery problemy:
1. Klasa wewnętrznie przechowuje początek i koniec zakresu w
postaci liczbowej (aby wykonywać operacje typu "liczba adresów IP
w zakresie", czy "powiększ zakres o kolejnych 400 adresów"), zaś
człowiek (programista) bardziej skłonny jest używać postaci znakowej
("xxx.xxx.xxx.xxx"). Transformacji może dokonać automagicznie
konstruktor klasy.
2. Chcąc zmienić wartość początku i/lub końca zakresu w obiekcie
trzeba pamiętać o zamianie adresu IP na liczbę. Metoda zamiany jest
dość złożona i trudna do zapamiętania, gdyż wymaga użycia metod
modułów socket oraz struct. Trzeba zatem bawić się w metody statyczne
lub dodatkowe funkcje.
3. Przy zmianie dowolnego z tych dwóch atrybutów trzeba pamiętać,
że zakres nie może być odwrócony, tzn. początek nie może być za końcem.
Pilnowanie tego może byc strasznie upierdliwe.
4. Często potrzebujemy odczytać wartości początku i końca zakresu
w postaci znakowej, np. aby zaprezentować wynik użytkownikowi.
Wymaga to albo przechowywania w obiekcie zarówno liczb jak i ich
odpowiedników znakowych (i aktualizować przy każdej zmianie wartości),
albo definiowania dodatkowych metod, które zwrócą string po
transformacji, albo tworzyć dodatkowe funkcje.

Wszystkie te cztery problemy załatwiają metody __get__() i __set__().
Przy nadawaniu i odczycie wartości mogą dokonywać automatycznej
transformacji z/na wartość liczbową (jeśli potrzeba), pilnować żeby
zakres nie był odwrócony i dostarczać "wirtualnych" atrybutów znakowych,
których wartość będzie generowana w locie.

Dwie małe metody, masa problemów z głowy.

sacre

unread,
Nov 28, 2009, 7:40:53 AM11/28/09
to
De(y)skryptory są osobnymi klasami a ich instancje przypisuje się do
atrybutów klas (przykład mam nadzieje wyjaśni co chciałem powiedzieć :) ).

Jeśli chcesz nauczyć się używania deskryptorów to polecam:
http://users.rcn.com/python/download/Descriptor.htm

A ty przykład:

# tak dla uproszczenia
addr2int = int
int2addr = str

class IpFieldDescriptor(object):
""" klasa deskryptora """

def __init__(self, int_field_name):
self.int_field_name = int_field_name

def __get__(self, obj, cls):
""" konwersja ze string do int """
assert obj is not None,'access only from instance!'
ip_int = getattr(obj, self.int_field_name, None)
if ip_int is not None:
return int2addr(ip_int)

def __set__(self, obj, value):
""" konwersja z int do string """
assert obj is not None,'access only from instance!'
ip_int = addr2int(value)
setattr(obj, self.int_field_name, ip_int)

class IpRange(object):
""" wlasciwa klasa """

start = IpFieldDescriptor('_start_int')
stop = IpFieldDescriptor('_stop_int')

def __init__(self, start, stop):
self.start = start
self.stop = stop


if __name__ == '__main__':
iprange = IpRange('9', '13')

# konstruktor
print iprange.start, type(iprange.start)
print iprange._start_int, type(iprange._start_int)
print iprange.stop, type(iprange.stop)
print iprange._stop_int, type(iprange._stop_int)

# ustawianie
iprange.start = '14'
iprange.stop = '20'

print iprange.start, type(iprange.start)
print iprange._start_int, type(iprange._start_int)
print iprange.stop, type(iprange.stop)
print iprange._stop_int, type(iprange._stop_int)


ps. co to są "dyskryptory" ? czy to się tak tłumaczy na nasz język ?

--
sacre

Rob Wolfe

unread,
Nov 28, 2009, 8:04:36 AM11/28/09
to
ak3031884 <ak30...@gmail.com> writes:

> Witam,
> zabieram si� za temat dyskryptor�w po raz ......no du�o tego by�o ale
> tym razem powiedzia�em sobie �e nie odpuszcze bo nie rozumiem ca�ego
> stanu rzeczy z dyskryptorami po co je wymy�lili doj�cie do sk�adowych
> klasy w pythonnie mo�emy uzyska� w bardzo prosyt spos�b prawda


>
> clsss myClass():
> def __init__(self, a, b):
> self.a = a
> self.b = b
> return
>
> my = Class()
> my.a =1
> my.b=2
>

> czysyt �adny kod, doj�cie jest a je�eli chcemy to zakapsu�kowa� to
> zawsz mo�emy zmienne ustawi� na
> self.__a b�dzie to zmienna praywatna kt�rej nie zmodyfikujemy
> z dyskryptorami b�dzie to wygl�da�o tak


>
> class myClass(object):
> def __init__(self, self, a, b):
> self.a = a
> self.b = b
>
> def __get__(self, obj, objtype):
> return self.a
>
> def __set__(self, obj, val):
> self.a = a
>

> 2 klasa nie wiem czy dobrze napisana bo nie rozumiem tego ale to ko�o
> tego ma wygl�da�.
> Tak czy inaczej wi�cej pisania, zagmatwane, moim skromnym zdaniem nie
> bardzo czytelne,
> wyt�umaczcie mi co w tym takiego dobrego i� jest to wprowadzane do
> ka�dego j�zyka programowania.

Zapewne znana Ci jest funkcja "property":
http://docs.python.org/library/functions.html?highlight=property#property

Czy masz jakie� w�tpliwo�ci, �e jest u�yteczna (szczeg�lnie
w kontek�cie wszechobecnych setter�w i getter�w)?

"Property" tworzy w�a�nie deskryptor, kt�ry wygl�da tak:

class property(object):

def __init__(self, fget=None, fset=None, fdel=None, doc=None):
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
self.__get = fget
self.__set = fset
self.__del = fdel
self.__doc__ = doc

def __get__(self, inst, type=None):
if inst is None:
return self
if self.__get is None:
raise AttributeError, "unreadable attribute"
return self.__get(inst)

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

def __delete__(self, inst):
if self.__del is None:
raise AttributeError, "can't delete attribute"
return self.__del(inst)

RW

ak3031884

unread,
Nov 28, 2009, 10:19:07 AM11/28/09
to
Tak ten przykład podoba mi sie i pokazuje słuszność stosowania __set__
i __get__, aczkolwiek w "starym stylu klas" można to też ładnie
napisać.

Powiedzcie mi jeszcze jaka jest różnica między funkcjami
object.__getattr__(self, name) a def __get__(self, obj, cls):
object.__setattr__(self, name, value) a def __set__(self, obj, value):

czytając http://docs.python.org/reference/datamodel.html jakoś nie
bardzo pojąłem wielkość różnicy tych funkcji.


ps. deskryptory :-)

Pozdrawiam


Daniel Mróz

unread,
Nov 28, 2009, 10:57:53 AM11/28/09
to
On 28.11.2009, sacre <sacr...@wp.pl> wrote:
> assert obj is not None,'access only from instance!'
Uczulam: asercje nie są sprawdzane przy prekompilacji z optymalizacją.

ak3031884

unread,
Nov 28, 2009, 2:45:09 PM11/28/09
to
To znaczy że ?


On 28 Lis, 16:57, Daniel Mróz <be...@alpha.pl> wrote:
> On 28.11.2009, sacre <sacre...@wp.pl> wrote:>          assert obj is not None,'access only from instance!'

Elus

unread,
Nov 28, 2009, 3:47:02 PM11/28/09
to
On 28 Lis, 20:45, ak3031884 <ak3031...@gmail.com> wrote:
> To znaczy że ?
>
> On 28 Lis, 16:57, Daniel Mróz <be...@alpha.pl> wrote:
>
>
>
> > On 28.11.2009, sacre <sacre...@wp.pl> wrote:>          assert obj is not None,'access only from instance!'
>
> > Uczulam: asercje nie są sprawdzane przy prekompilacji z optymalizacją.


To z grubsza znaczy, że wszelkie wyrażenia `assert` zostaną usunięte w
procesie optymalizacji:

$ python -c "assert 1==2"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
$ python -Oc "assert 1==2" # cicho

ak3031884

unread,
Nov 28, 2009, 9:33:50 PM11/28/09
to
On 28 Lis, 21:47, Elus <tomasz.ele...@gmail.com> wrote:
> On 28 Lis, 20:45, ak3031884 <ak3031...@gmail.com> wrote:
>
> > To znaczy że ?
>
ok ale jak to sie ma do różnic miedzy funkcjami

object.__getattr__(self, name) a def __get__(self, obj, cls):
object.__setattr__(self, name, value) a def __set__(self, obj,
value):

?

Rob Wolfe

unread,
Nov 29, 2009, 6:52:55 AM11/29/09
to
ak3031884 <ak30...@gmail.com> writes:

> Tak ten przyk�ad podoba mi sie i pokazuje s�uszno�� stosowania __set__
> i __get__, aczkolwiek w "starym stylu klas" mo�na to te� �adnie
> napisaďż˝.
>
> Powiedzcie mi jeszcze jaka jest r�nica mi�dzy funkcjami


> object.__getattr__(self, name) a def __get__(self, obj, cls):
> object.__setattr__(self, name, value) a def __set__(self, obj, value):
>

> czytaj�c http://docs.python.org/reference/datamodel.html jako� nie
> bardzo poj��em wielko�� r�nicy tych funkcji.

Je�li masz ambicj� zrozumienia deskryptor�w, to musisz przeczyta� opis
(najlepszy w sieci, napisany przez tw�rc� tej koncepcji),
do kt�rego link ju� Ci zosta� podany:
http://users.rcn.com/python/download/Descriptor.htm

Gdy tam zajrzysz, to znajdziesz kluczowďż˝ definicjďż˝ dla zrozumienia
tego mechanizmu:

def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

Kluczowa zasada to kolejno�� wywo�a�:
1. __getattribute__ jest wo�ana zawsze jako pierwsza
2. __get__ jest wo�ana tylko dla atrybut�w, kt�re maj�
zdefiniowanďż˝ takďż˝ metodďż˝, czyli sďż˝ deskryptorami
3. __getattr__ jest wo�ana zawsze jako ostatnia
i tylko wtedy, gdy powy�szy mechanizm nie by� w stanie
odnale�� sk�adowej


Czyli gdy mamy zdefiniowanďż˝ tylko `__getattribute__`,
to wo�ana jest zawsze:

class A(object):
def __init__(self):
self.x = 99

def __getattribute__(self, name):
print '__getattribute__: %r' % name
v = object.__getattribute__(self, name)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

>>> a = A()
>>> a.x
__getattribute__: 'x'
99
>>> a.y
__getattribute__: 'y'


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/tmp/python-4766uIx.py", line 7, in __getattribute__
AttributeError: 'A' object has no attribute 'y'


Gdy mamy zdefiniowan� `__getattr__`, to wo�ana jest tylko
przy odwo�aniu do *niezdefiniowanej* sk�adowej:


class B(object):
def __init__(self):
self.x = 99

def __getattr__(self, name):
print '__getattr__: %r' % name
if name == 'y':
return self.x * 10 # odwolanie do self.x nie powoduje zapetlenia
raise AttributeError('%r object has no attribute %r'
% (self.__class__.__name__, name))

>>> b = B()
>>> b.x
99
>>> b.y
__getattr__: 'y'
990
>>> b.z
__getattr__: 'z'


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/tmp/python-4766gSA.py", line 10, in __getattr__
AttributeError: 'B' object has no attribute 'z'


Gdy mamy zdefiniowane zar�wno `__getattribute__` jak i `__getattr__`,
to wywo�ywane s� w z g�ry przyj�tej kolejno�ci, czyli na pocz�tku
`__getattribute__`, a na ko�cu `__getattr__` (gdy jest odwo�anie
do *niezdefiniowanej* sk�adowej):

class C(object):
def __init__(self):
self.x = 99

def __getattribute__(self, name):
print '__getattribute__: %r' % name
v = object.__getattribute__(self, name)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

def __getattr__(self, name):
print '__getattr__: %r' % name
if name == 'y':
return self.x * 10 # odwolanie do self.x nie powoduje zapetlenia
raise AttributeError('%r object has no attribute %r'
% (self.__class__.__name__, name))

>>> c = C()
>>> c.x
__getattribute__: 'x'
99
>>> c.y
__getattribute__: 'y'
__getattr__: 'y'
__getattribute__: 'x'
990
>>> c.z
__getattribute__: 'z'
__getattr__: 'z'
__getattribute__: '__class__'


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/tmp/python-4766tcG.py", line 17, in __getattr__
AttributeError: 'C' object has no attribute 'z'


I teraz, gdy do tej klasy dorzucimy definicjďż˝ `__get__`, to co siďż˝ stanie?
Mogďż˝ siďż˝ dziaďż˝ dziwne rzeczy, gdyďż˝ `__get__` w takim przypadku nie ma
najmniejszego sensu:


class D(object):
def __init__(self):
self.x = 99

def __getattribute__(self, name):
print '__getattribute__: %r' % name
v = object.__getattribute__(self, name)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

def __get__(self, instance, owner):
print '__get__: %r' % owner
return self.x

def __getattr__(self, name):
print '__getattr__: %r' % name
if name == 'y':
return self.x * 10 # odwolanie do self.x nie powoduje zapetlenia
raise AttributeError('%r object has no attribute %r'
% (self.__class__.__name__, name))


>>> d = D()
>>> d.x
__getattribute__: 'x'
99
>>> d.y
__getattribute__: 'y'
__getattr__: 'y'
__getattribute__: 'x'
990
>>> d.z
__getattribute__: 'z'
__getattr__: 'z'
__getattribute__: '__class__'


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/tmp/python-4766U7Y.py", line 21, in __getattr__
File "/tmp/python-4766U7Y.py", line 9, in __getattribute__
TypeError: unbound method __get__() must be called with D instance as first argument (got NoneType instance instead)

Zgodnie z dokumentacjďż˝ [1]_ ma sens tylko dla:
"""
The following methods (przyp. tlum. __get__, __set__, __delete__) only
apply when an instance of the class containing the method
(a so-called descriptor class) appears in the class dictionary of
another new-style class, known as the owner class.
"""

czyli po naszemu:

"""
Metody __get__, __set__ i __delete__ majďż˝ zastosowanie wtedy i tylko wtedy,
gdy instancja klasy zawieraj�ca te metody (tzw. deskryptor) stanowi sk�adow�
innej klasy nowego stylu.
"""

W zwi�zku z tym deskryptor ma sens w takim przypadku jak ten, gdzie mamy
oddzieln� klas� definiuj�c� sk�adow� i jak�� klas� zawierj�c�
t� sk�adow�:

class E(object):
def __init__(self, val):
self.val = val

def __get__(self, instance, owner):
print '__get__: %r' % owner.__class__.__name__
return self.val


class F(object):
def __init__(self):
self.x = E(99)

def __getattribute__(self, name):
print '__getattribute__: %r' % name
v = object.__getattribute__(self, name)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

def __getattr__(self, name):
print '__getattr__: %r' % name
if name == 'y':
return self.x * 10 # odwolanie do self.x nie powoduje zapetlenia
raise AttributeError('%r object has no attribute %r'
% (self.__class__.__name__, name))


>>> f = F()
>>> f.x
__getattribute__: 'x'
__getattribute__: '__class__'
__get__: 'F'
99
>>> f.y
__getattribute__: 'y'
__getattr__: 'y'
__getattribute__: 'x'
__getattribute__: '__class__'
__get__: 'F'
990
>>> f.z
__getattribute__: 'z'
__getattr__: 'z'
__getattribute__: '__class__'


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/tmp/python-4766uPl.py", line 26, in __getattr__
AttributeError: 'F' object has no attribute 'z'


A teraz po�wicz ten temat tak z tydzie� w r�nych wariantach
i jest pewna szansa, �e co� si� zacznie klarowa�. ;)

.. [1] http://docs.python.org/reference/datamodel.html?highlight=__getattr__#object.__getattribute__

RW

ak3031884

unread,
Nov 29, 2009, 3:01:55 PM11/29/09
to
Wielkie dzięki super opis.

On 29 Lis, 12:52, Rob Wolfe <r...@smsnet.pl> wrote:


> ak3031884 <ak3031...@gmail.com> writes:
> > Tak ten przykład podoba mi sie i pokazuje słuszność stosowania __set__
> > i __get__, aczkolwiek w  "starym stylu klas" można to też ładnie
> > napisać.
>

> > Powiedzcie mi jeszcze jaka jest różnica między funkcjami


> > object.__getattr__(self, name) a   def __get__(self, obj, cls):
> > object.__setattr__(self, name, value) a def __set__(self, obj, value):
>

> > czytająchttp://docs.python.org/reference/datamodel.htmljakoś nie


> > bardzo pojąłem wielkość różnicy tych funkcji.
>

> Jeśli masz ambicję zrozumienia deskryptorów, to musisz przeczytać opis
> (najlepszy w sieci, napisany przez twórcę tej koncepcji),
> do którego link już Ci został podany:http://users.rcn.com/python/download/Descriptor.htm
>
> Gdy tam zajrzysz, to znajdziesz kluczową definicję dla zrozumienia


> tego mechanizmu:
>
> def __getattribute__(self, key):
>     "Emulate type_getattro() in Objects/typeobject.c"
>     v = object.__getattribute__(self, key)
>     if hasattr(v, '__get__'):
>        return v.__get__(None, self)
>     return v
>

> Kluczowa zasada to kolejność wywołań:
> 1. __getattribute__ jest wołana zawsze jako pierwsza
> 2. __get__ jest wołana tylko dla atrybutów, które mają
>    zdefiniowaną taką metodę, czyli są deskryptorami
> 3. __getattr__ jest wołana zawsze jako ostatnia
>   i tylko wtedy, gdy powyższy mechanizm nie był w stanie
>   odnaleźć składowej
>
> Czyli gdy mamy zdefiniowaną tylko `__getattribute__`,
> to wołana jest zawsze:


>
> class A(object):
>     def __init__(self):
>         self.x = 99
>
>     def __getattribute__(self, name):
>         print '__getattribute__: %r' % name
>         v = object.__getattribute__(self, name)
>         if hasattr(v, '__get__'):
>             return v.__get__(None, self)
>         return v
>
> >>> a = A()
> >>> a.x
>
> __getattribute__: 'x'
> 99>>> a.y
>
> __getattribute__: 'y'
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/tmp/python-4766uIx.py", line 7, in __getattribute__
> AttributeError: 'A' object has no attribute 'y'
>

> Gdy mamy zdefiniowaną `__getattr__`, to wołana jest tylko
> przy odwołaniu do *niezdefiniowanej* składowej:


>
> class B(object):
>     def __init__(self):
>         self.x = 99
>
>     def __getattr__(self, name):
>         print '__getattr__: %r' % name
>         if name == 'y':
>             return self.x * 10  # odwolanie do self.x nie powoduje zapetlenia
>         raise AttributeError('%r object has no attribute %r'
>                              % (self.__class__.__name__, name))
>
> >>> b = B()
> >>> b.x
> 99
> >>> b.y
>
> __getattr__: 'y'
> 990>>> b.z
>
> __getattr__: 'z'
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/tmp/python-4766gSA.py", line 10, in __getattr__
> AttributeError: 'B' object has no attribute 'z'
>

> Gdy mamy zdefiniowane zarówno `__getattribute__` jak i `__getattr__`,
> to wywoływane są w z góry przyjętej kolejności, czyli na początku
> `__getattribute__`, a na końcu `__getattr__` (gdy jest odwołanie
> do *niezdefiniowanej* składowej):

> I teraz, gdy do tej klasy dorzucimy definicję `__get__`, to co się stanie?
> Mogą się dziać dziwne rzeczy, gdyż `__get__` w takim przypadku nie ma

> Zgodnie z dokumentacją [1]_ ma sens tylko dla:


> """
> The following methods (przyp. tlum. __get__, __set__, __delete__) only
> apply when an instance of the class containing the method
> (a so-called descriptor class) appears in the class dictionary of
> another new-style class, known as the owner class.
> """
>
> czyli po naszemu:
>
> """

> Metody __get__, __set__ i __delete__ mają zastosowanie wtedy i tylko wtedy,
> gdy instancja klasy zawierająca te metody (tzw. deskryptor) stanowi składową
> innej klasy nowego stylu.
> """
>
> W związku z tym deskryptor ma sens w takim przypadku jak ten, gdzie mamy
> oddzielną klasę definiującą składową i jakąś klasę zawierjącą
> tę składową:

> A teraz poćwicz ten temat tak z tydzień w różnych wariantach
> i jest pewna szansa, że coś się zacznie klarować. ;)
>
> .. [1]http://docs.python.org/reference/datamodel.html?highlight=__getattr__...
>
> RW

0 new messages