Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Peter Otten <__peter__@web.de> Newsgroups: de.comp.lang.python Subject: Re: [Python-de] "property-init"-decorator Date: Wed, 27 May 2020 17:13:10 +0200 Organization: None Lines: 133 Message-ID: References: <875zci8zut.fsf@orrococo> <4719790.vIyLdRSyTD@palindrom> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Trace: news.uni-berlin.de mgVrm8vveHSLWYg35XfD6QThAg5rMNN0ouuFK3l+ZGmQ== Return-Path: <__peter__@web.de> X-Original-To: python-de@python.org Delivered-To: python-de@mail.python.org Authentication-Results: mail.python.org; dkim=pass reason="1024-bit key; unprotected key" header.d=web.de header.i=@web.de header.b=lSAhAR3x; dkim-adsp=pass; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1590592403; bh=8kmsqJwJ2nVx2N/R86VJsNw2aNLD5ghvfmbgzMgQNn0=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=lSAhAR3xjrMPSHB249sAZwPt5Munp8gas9ITBU77MFp6rERvJE3/w9I0ve7DjZv7c dxxHyP/V3gW2NyBlxr3+lDAvwvfPYq+lV5lRO67J5woSjna/ecFAgiLyZP1UymZjBk pMci2/g+ikFsVAw4xD8w/cGyIoN4m7EZBHbmo2XM= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 User-Agent: KMail/4.13.3 (Linux/3.13.0-170-generic; KDE/4.13.3; x86_64; ; ) In-Reply-To: X-Provags-ID: V03:K1:H+pgmeoh/JM1623vDgwSFO3LTGwQeLvQ+KF08ZxrWprd/ohprYh pZVmHO0qJ4qe9tsJHHgmzhyOIzC8GRZCVjnecqQIOJBtCBRAg1+nDeI6FcIJW3gCXr/07eh XMuqIuvsazI8dUeMYzQ1DLilGJG64MN1tAv6u8fzKp9sIF6hmpO1qCBTv/6rC7YHrz6wrxK KAQm4/mXeXZ2qWnDbJYlw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:EVREGDT7QHo=:LljhCDVoHYJeeWrmtfZEx1 oTwcaOt891iUo2vJ0QA8L/Ho8+LkYzJJ0JzMe8oTs1o63wLBPS1uiRNwbHRkk9oW1ms5uc8Rf O+gN34OrMIxf2UucDm+LdZnrLb2tTvpPOhzz5eGVXpVAF7R0J2W5Ft/VoQevBSo+5KjAAOSrA g/0wW5gdrI68mKKIZ2IcbGdzS82McjhcX9PH0saGa/gm2kCGsAzJjZaN28L4AP5Dih+nVMxvR DgAGVdeNfWSy1zXEfGG2jMQ+tFKxmJtFTDptujMo45lK0jwCRhU7ysCM+2XJiqjLNN6Y9rm/w aXLK8d8HkOTUrnHp67RRmUWp6GkXpBPI5H75bKRPvuoxF+8YVUNhURVlZw9Xe6Kfm0A1tGume UiORAE1CM4DYo2aGGmfFsykT6k1xTfEUKPOtWNVuHKIi2MuWkdy0d4fHuzobrHpAQiYFHkXYF W1d3A7Tsl2AZe+73oU7AmNw9v+o8h/8VMU6sECBHlv05Yf2Xk+EPBphIqm7mmvDat4hmaJt63 KUmurAzAKz7uUFvt6fe8gdGvpK27h1QBbBs5oBNsfEt+xUsQT5QvC9r6uD02osBRUtvoJRyCo d6k+0tPUQg2Ey6nklukRoskmoTKDSO01spix6aEExwtcGoj8vLbyjsYMRcVA4tIiVh7DttzNz g83DNoGoYeicqj9QXyL5zzKcj21GzX1IL8aG/3HLpQpfNAWGD5RYrWqx1yPiRtmIQYaSA7aOq 6xthv8HIfjZiA7mexYS5SOIamIkcrPPIOGJf8DS6SgrT1vWwt9ZxN7eL73076CTRTWxi2cfML ivEzAFkkOJm1NyqeSjmHVdrMWTH+O5o0qqGx/iLqT9Nw8MMqz0oHS/qgX/Tl9ud0nzjHHbPqA 6md1nlVAcGSnLoskAN1I4KKqPHqqXzHGpqO7avKcqBqfnGS3IjfD7FUNKVd5RTsEaTHwqOWfz Cb3EYaSlTPyAma5U5OW138pYPEjkeUlep98P6n05FDbn0c+PmODNaP5IMjOd5YnjDNHiF/o7c 3Y8KpBASPVFWIqfsTQSSoGpVMmGybmMaeaAPmZA8Uotpuge9fjx9nMLXqJU7eytA/QyXpDg2h CYsdqgb7KEouWAc+PhVSbFi6l4qO6LJzvtFt81T8zA2qxuUfZp6U7+/XKrjhrFYXS7Z/QhZXo aexxA4OiCAq+lHUZG303Os2TGQeIUo0MzciLsfnmNAWqXN/taeyqs2CsAud8HzdrYgd6zA/ek +EoQA1YhZsAHXqm5g X-BeenThere: python-de@python.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: Die Deutsche Python Mailingliste List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: <4719790.vIyLdRSyTD@palindrom> X-Mailman-Original-References: <875zci8zut.fsf@orrococo> Xref: csiph.com de.comp.lang.python:5639 Am Mi Mai 27 2020, 10:27:31 schrieb Hartmut Goebel: > Am 26.05.20 um 17:44 schrieb =D0=9El=D0=B5 =D0=85tr=D0=B5=D1=96=D1=81= h=D0=B5r: > > Wie bringt man die enger zusammen? Ein @myprop.init gibt es ja > > offensichtlich nicht und kann man auch nicht so ohne weiteres anleg= en, > > oder? Oder was w=C3=A4re ein sinnvolles Pattern hier? >=20 > Du k=C3=B6nntest eine eigene "Property" class implementieren, die ein= en > weiteren Docorator "initialisiere" hat. Allerdings bleibt immer noch= > das Problem, dass Du diese Funktion in __init__ irgendwie aufrufen > musst. Du m=C3=BCsstest in __init__ hergehen und alle properies der K= lasse > (self.__class__) finden und deren initalizer aufrufen. >=20 > Ich habe die genau Funktionsweise von Properties nicht im Kopf, aber > irgendwie sollte das gehen. Vielleicht schaust Du man in den PEP zu > properties, dort gibt es sicher Details. >=20 > Allerdings gibt es mindestens zwei Haken: >=20 > 1. Wenn die initializer in eine bestimmten Reihenfolge aufgerufen wer= den > m=C3=BCssen, dann musst Du sie doch wieder benennen. Denn sonst bekom= mstt Du > keine Reihenfolge. Die Reihenfolge kann durch die Positionierung in der Klasse bestimmt we= rden: >>> class A: ... foo =3D 1 ... bar =3D 2 ...=20 >>> class B: ... bar =3D 2 ... foo =3D 1 ...=20 >>> vars(A).keys() dict_keys(['__module__', 'foo', 'bar', '__dict__', '__weakref__', '__do= c__']) >>> vars(B).keys() dict_keys(['__module__', 'bar', 'foo', '__dict__', '__weakref__', '__do= c__']) >=20 > 2. Wie ruft man die iniatlizer =C3=BCberhaupt auf? Da ben=C3=B6tigt man die Mithilfe der Eigent=C3=BCmer(meta)klasse. Nachfolgend eine einfache Implementierung, die die Properties anhand ih= rer=20 Klasse identifiziert: $ cat init_property.py missing =3D object() class myproperty(property): finit =3D None default =3D missing def initializer(self, f): self.finit =3D f return self def init(self, owner): if self.finit is not None: self.finit(owner) elif self.default is not missing: # eventuell "_" + self.name, um den Aufruf des Setters # zu vermeiden setattr(owner, self.name, self.default) def __set_name__(self, owner, name): self.name =3D name class Cfg: @classmethod def myproperties(cls): return [p for p in vars(cls).values() if isinstance(p, myproper= ty)] def __init__(self): for p in self.myproperties(): p.init(self) @myproperty def foo(self): return self._foo @foo.setter def foo(self, value): assert 0 <=3D value < 100 self._foo =3D value @foo.initializer def foo(self): self._foo =3D 42 @myproperty def bar(self): return self._bar @bar.setter def bar(self, value): assert isinstance(value, int) self._bar =3D value bar.default =3D 123 c =3D Cfg() print(c.foo) # 42, im Initializer gesetzt print(c.bar) # 123, default-Attribut c.foo =3D 24 # OK c.bar =3D "spam" # Exception $ python3.8 init_property.py 42 123 Traceback (most recent call last): File "init_property.py", line 59, in c.bar =3D "spam" File "init_property.py", line 50, in bar assert isinstance(value, int) AssertionError $ Wer's gerne eleganter h=C3=A4tte, k=C3=B6nnte sich ja mal den Quellcode= der dataclasses=20 zu Gem=C3=BCte f=C3=BChren...