Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.lang.python > #5639

Re: [Python-de] "property-init"-decorator

From Peter Otten <__peter__@web.de>
Newsgroups de.comp.lang.python
Subject Re: [Python-de] "property-init"-decorator
Date 2020-05-27 17:13 +0200
Organization None
Message-ID <mailman.155.1590592405.27263.python-de@python.org> (permalink)
References <875zci8zut.fsf@orrococo> <c36dda0a-50b6-7454-2da4-1f3bff5828cf@goebel-consult.de> <4719790.vIyLdRSyTD@palindrom>

Show all headers | View raw


Am Mi Mai 27 2020, 10:27:31 schrieb Hartmut Goebel:
> Am 26.05.20 um 17:44 schrieb Оlе Ѕtrеісhеr:
> > Wie bringt man die enger zusammen? Ein @myprop.init gibt es ja
> > offensichtlich nicht und kann man auch nicht so ohne weiteres anlegen,
> > oder? Oder was wäre ein sinnvolles Pattern hier?
> 
> Du könntest eine eigene "Property" class implementieren, die einen
> weiteren Docorator "initialisiere" hat.  Allerdings bleibt immer noch
> das Problem, dass Du diese Funktion in __init__ irgendwie aufrufen
> musst. Du müsstest in __init__ hergehen und alle properies der Klasse
> (self.__class__) finden und deren initalizer aufrufen.
> 
> 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.
> 
> Allerdings gibt es mindestens zwei Haken:
> 
> 1. Wenn die initializer in eine bestimmten Reihenfolge aufgerufen werden
> müssen, dann musst Du sie doch wieder benennen. Denn sonst bekommstt Du
> keine Reihenfolge.

Die Reihenfolge kann durch die Positionierung in der Klasse bestimmt werden:

>>> class A:
...    foo = 1
...    bar = 2
... 
>>> class B:
...    bar = 2
...    foo = 1
... 
>>> vars(A).keys()
dict_keys(['__module__', 'foo', 'bar', '__dict__', '__weakref__', '__doc__'])
>>> vars(B).keys()
dict_keys(['__module__', 'bar', 'foo', '__dict__', '__weakref__', '__doc__'])

> 
> 2. Wie ruft man die iniatlizer überhaupt auf?

Da benötigt man die Mithilfe der Eigentümer(meta)klasse.
Nachfolgend eine einfache Implementierung, die die Properties anhand ihrer 
Klasse identifiziert:

$ cat init_property.py
missing = object()


class myproperty(property):
    finit = None
    default = missing

    def initializer(self, f):
        self.finit = 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 = name


class Cfg:
    @classmethod
    def myproperties(cls):
        return [p for p in vars(cls).values() if isinstance(p, myproperty)]

    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 <= value < 100
        self._foo = value

    @foo.initializer
    def foo(self):
        self._foo = 42

    @myproperty
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        assert isinstance(value, int)
        self._bar = value

    bar.default = 123

c = Cfg()
print(c.foo)  # 42, im Initializer gesetzt
print(c.bar)  # 123, default-Attribut
c.foo = 24  # OK
c.bar = "spam"  # Exception

$ python3.8 init_property.py
42
123
Traceback (most recent call last):
  File "init_property.py", line 59, in <module>
    c.bar = "spam"
  File "init_property.py", line 50, in bar
    assert isinstance(value, int)
AssertionError
$

Wer's gerne eleganter hätte, könnte sich ja mal den Quellcode der dataclasses 
zu Gemüte führen...

Back to de.comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

"property-init"-decorator ole-usenet-spam@gmx.net (Оlе Ѕtrеісhеr) - 2020-05-26 17:44 +0200
  Re: [Python-de] "property-init"-decorator Julian Gethmann <mail.python.org@gethmann.org> - 2020-05-26 18:07 +0200
  Re: [Python-de] "property-init"-decorator Hartmut Goebel <h.goebel@goebel-consult.de> - 2020-05-27 10:27 +0200
  Re: "property-init"-decorator "Andreas B." <ab@sysing.de> - 2020-05-27 13:18 +0200
  Re: [Python-de] "property-init"-decorator Gregor Engberding <gregor@landit.de> - 2020-05-27 17:04 +0200
  Re: [Python-de] "property-init"-decorator Peter Otten <__peter__@web.de> - 2020-05-27 17:13 +0200
  Re: [Python-de] "property-init"-decorator Hartmut Goebel <h.goebel@goebel-consult.de> - 2020-05-31 10:13 +0200
  Re: [Python-de] "property-init"-decorator Peter Otten <__peter__@web.de> - 2020-05-31 15:37 +0200

csiph-web