Ich möchte verstehen, wie die eingebaute Funktion property funktioniert. Was mich verwirrt ist, dass property auch als Dekorateur verwendet werden kann, aber nur Argumente benötigt, wenn es als integrierte Funktion verwendet wird und nicht, wenn es als Dekorateur verwendet wird.

Dieses Beispiel stammt aus der Dokumentation:

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.")

Die Argumente von property sind getx, setx, delx und eine Dokumentzeichenfolge.

Im folgenden Code wird property als Dekorateur verwendet. Das Objekt davon ist die Funktion x, aber im obigen Code ist in den Argumenten kein Platz für eine Objektfunktion.

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

Und wie werden die Dekoratoren x.setter und x.deleter erstellt? Ich bin verwirrt.

937
ashim 27 Juni 2013 im 00:47

13 Antworten

Beste Antwort

Die Funktion property() gibt ein spezielles Deskriptorobjekt zurück:

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

Dieses Objekt verfügt über zusätzliche Methoden:

>>> 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>

Diese fungieren auch als Dekorateure. Sie geben ein neues Eigenschaftsobjekt zurück:

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

Das ist eine Kopie des alten Objekts, wobei jedoch eine der Funktionen ersetzt wurde.

Denken Sie daran, dass die @decorator -Syntax nur syntaktischer Zucker ist. die Syntax:

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

Bedeutet wirklich das Gleiche wie

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

Also foo wird die Funktion durch property(foo) ersetzt, was wir oben gesehen haben, ist ein spezielles Objekt. Wenn Sie dann @foo.setter() verwenden, rufen Sie die oben gezeigte property().setter -Methode auf, die eine neue Kopie der Eigenschaft zurückgibt, diesmal jedoch, wobei die Setter-Funktion durch die dekorierte Methode ersetzt wird.

In der folgenden Sequenz wird mithilfe dieser Decorator-Methoden auch eine Full-On-Eigenschaft erstellt.

Zuerst erstellen wir einige Funktionen und ein property Objekt mit nur einem Getter:

>>> 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

Als nächstes verwenden wir die .setter() Methode, um einen Setter hinzuzufügen:

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

Zuletzt fügen wir einen Deleter mit der Methode .deleter() hinzu:

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

Last but not least fungiert das property -Objekt als Deskriptorobjekt, also hat es .__get__(), .__set__() und .__delete__() Methoden zum Einbinden, Einstellen und Löschen von Instanzattributen:

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

Das Descriptor Howto enthält eine reine Python-Beispielimplementierung vom Typ property() ::

class Property:
    "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__)
969
Boris 20 Okt. 2019 im 19:02

Folgendes:

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

Ist das gleiche wie:

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

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, _x_set, _x_del, 
                    "I'm the 'x' property.")

Ist das gleiche wie:

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

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, doc="I'm the 'x' property.")
    x = x.setter(_x_set)
    x = x.deleter(_x_del)

Ist das gleiche wie:

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

    def _x_get(self):
        return self._x
    x = property(_x_get, doc="I'm the 'x' property.")

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

    def _x_del(self):
        del self._x
    x = x.deleter(_x_del)

Welches ist das gleiche wie:

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
47
Bill Moore 24 Mai 2017 im 18:38

In der Dokumentation heißt es, dass dies nur eine Verknüpfung zum Erstellen schreibgeschützter Eigenschaften ist. Damit

@property
def x(self):
    return self._x

Ist äquivalent zu

def getx(self):
    return self._x
x = property(getx)
187
λuser 15 Juli 2016 im 20:45

Der erste Teil ist einfach:

@property
def x(self): ...

Ist das gleiche wie

def x(self): ...
x = property(x)
  • Dies ist wiederum die vereinfachte Syntax zum Erstellen eines property mit nur einem Getter.

Der nächste Schritt wäre, diese Eigenschaft mit einem Setter und einem Deleter zu erweitern. Und dies geschieht mit den entsprechenden Methoden:

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

Gibt eine neue Eigenschaft zurück, die alles vom alten x plus dem angegebenen Setter erbt.

x.deleter funktioniert genauso.

83
glglgl 26 Juni 2013 im 20:53

Hier ist ein minimales Beispiel dafür, wie @property implementiert werden kann:

class Thing:
    def __init__(self, my_word):
        self._word = my_word 
    @property
    def word(self):
        return self._word

>>> print( Thing('ok').word )
'ok'

Andernfalls bleibt word eine Methode anstelle einer Eigenschaft.

class Thing:
    def __init__(self, my_word):
        self._word = my_word
    def word(self):
        return self._word

>>> print( Thing('ok').word() )
'ok'
105
AlexG 15 Feb. 2017 im 00:46

property ist eine Klasse hinter dem @property Dekorateur.

Sie können dies jederzeit überprüfen:

print(property) #<class 'property'>

Ich habe das Beispiel von help(property) umgeschrieben, um zu zeigen, dass die @property -Syntax

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

    @property 
    def x(self):
        return self._x

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

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

c = C()
c.x="a"
print(c.x)

Ist funktional identisch mit der property() Syntax:

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

    def g(self):
        return self._x

    def s(self, v):
        self._x = v

    def d(self):
        del self._x

    prop = property(g,s,d)

c = C()
c.x="a"
print(c.x)

Wie Sie sehen, gibt es keinen Unterschied, wie wir die Immobilie nutzen.

Zur Beantwortung der Frage wird @property Decorator über die Klasse property implementiert.


Die Frage ist also, die Klasse property ein wenig zu erklären. Diese Linie:

prop = property(g,s,d)

War die Initialisierung. Wir können es so umschreiben:

prop = property(fget=g,fset=s,fdel=d)

Die Bedeutung von fget, fset und fdel:

 |    fget
 |      function to be used for getting an attribute value
 |    fset
 |      function to be used for setting an attribute value
 |    fdel
 |      function to be used for del'ing an attribute
 |    doc
 |      docstring

Das nächste Bild zeigt die Drillinge aus der Klasse property:

enter image description here

__get__, __set__ und __delete__ sollen überschrieben. Dies ist die Implementierung des Deskriptormusters in Python.

Im Allgemeinen ist ein Deskriptor ein Objektattribut mit "Bindungsverhalten", dessen Attributzugriff durch Methoden im Deskriptorprotokoll überschrieben wurde.

Wir können auch die Eigenschaftsmethoden setter, getter und deleter verwenden, um die Funktion an die Eigenschaft zu binden. Überprüfen Sie das nächste Beispiel. Die Methode s2 der Klasse C setzt die Eigenschaft verdoppelt .

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

    def g(self):
        return self._x

    def s(self, x):
        self._x = x

    def d(self):
        del self._x

    def s2(self,x):
        self._x=x+x


    x=property(g)
    x=x.setter(s)
    x=x.deleter(d)      


c = C()
c.x="a"
print(c.x) # outputs "a"

C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x) # outputs "aa"
6
prosti 26 Mai 2019 im 21:10

Dieser Punkt wurde von vielen Leuten dort oben geklärt, aber hier ist ein direkter Punkt, den ich gesucht habe. Dies ist meiner Meinung nach wichtig, um mit dem @ property-Dekorateur zu beginnen. z.B:-

class UtilityMixin():
    @property
    def get_config(self):
        return "This is property"

Der Aufruf der Funktion "get_config ()" funktioniert folgendermaßen.

util = UtilityMixin()
print(util.get_config)

Wenn Sie bemerken, dass ich keine "()" Klammern zum Aufrufen der Funktion verwendet habe. Dies ist die grundlegende Sache, nach der ich nach dem @ property-Dekorateur gesucht habe. Damit Sie Ihre Funktion wie eine Variable verwenden können.

16
Devendra Bhat 26 Nov. 2018 im 06:39

Im Folgenden finden Sie ein weiteres Beispiel, wie @property helfen kann, wenn Code umgestaltet werden muss, der aus hier (ich fasse es nur unten zusammen):

Stellen Sie sich vor, Sie haben eine Klasse Money wie folgt erstellt:

class Money:
    def __init__(self, dollars, cents):
        self.dollars = dollars
        self.cents = cents

Und ein Benutzer erstellt eine Bibliothek in Abhängigkeit von dieser Klasse, in der er z.

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.

Nehmen wir nun an, Sie möchten Ihre Klasse Money ändern und die Attribute dollars und cents entfernen. Stattdessen möchten Sie nur den Gesamtbetrag der Cent verfolgen:

class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

Wenn der oben genannte Benutzer nun versucht, seine Bibliothek wie zuvor auszuführen

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))

Es wird zu einem Fehler führen

AttributeError: Das Objekt 'Geld' hat kein Attribut 'Dollar'.

Das bedeutet, dass jetzt jeder, der sich auf Ihre ursprüngliche Money Klasse verlässt, alle Codezeilen ändern muss, in denen dollars und cents verwendet werden, was sehr schmerzhaft sein kann ... Also, wie könnte dies vermieden werden? Mit @property!

Das ist wie:

class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

    # Getter and setter for dollars...
    @property
    def dollars(self):
        return self.total_cents // 100

    @dollars.setter
    def dollars(self, new_dollars):
        self.total_cents = 100 * new_dollars + self.cents

    # And the getter and setter for cents.
    @property
    def cents(self):
        return self.total_cents % 100

    @cents.setter
    def cents(self, new_cents):
        self.total_cents = 100 * self.dollars + new_cents

Wenn wir jetzt aus unserer Bibliothek anrufen

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.

Es wird wie erwartet funktionieren und wir mussten keine einzige Codezeile in unserer Bibliothek ändern! Tatsächlich müssten wir nicht einmal wissen, dass sich die Bibliothek, von der wir abhängig sind, geändert hat.

Auch das setter funktioniert gut:

money.dollars += 2
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 12 cents.

money.cents += 10
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 22 cents.

Sie können @property auch in abstrakten Klassen verwenden. Ich gebe hier ein minimales Beispiel hier.

39
Cleb 16 Sept. 2019 im 21:42

Die beste Erklärung finden Sie hier: Python @Property Explained - Wie und wann? (Vollständige Beispiele) von Selva Prabhakaran | Veröffentlicht am 5. November 2018

Es half mir zu verstehen, WARUM nicht nur WIE.

https://www.machinelearningplus.com/python/python-property/

1
Victor Wang 25 Feb. 2020 im 03:50

Beginnen wir mit Python-Dekoratoren.

Ein Python-Dekorator ist eine Funktion, mit der Sie einer bereits definierten Funktion einige zusätzliche Funktionen hinzufügen können.

In Python ist alles ein Objekt. Funktionen in Python sind erstklassige Objekte, dh sie können von einer Variablen referenziert, in die Listen aufgenommen, als Argumente an eine andere Funktion usw. übergeben werden.

Betrachten Sie das folgende Code-Snippet.

def decorator_func(fun):
    def wrapper_func():
        print("Wrapper function started")
        fun()
        print("Given function decorated")
        # Wrapper function add something to the passed function and decorator 
        # returns the wrapper function
    return wrapper_func

def say_bye():
    print("bye!!")

say_bye = decorator_func(say_bye)
say_bye()

# Output:
#  Wrapper function started
#  bye
#  Given function decorated

Hier können wir sagen, dass die Decorator-Funktion unsere say_hello-Funktion geändert und einige zusätzliche Codezeilen hinzugefügt hat.

Python-Syntax für Dekorateur

def decorator_func(fun):
    def wrapper_func():
        print("Wrapper function started")
        fun()
        print("Given function decorated")
        # Wrapper function add something to the passed function and decorator 
        # returns the wrapper function
    return wrapper_func

@decorator_func
def say_bye():
    print("bye!!")

say_bye()

Lassen Sie uns alles abschließen als mit einem Fallszenario, aber vorher lassen Sie uns über einige Hoppla-Prinzipien sprechen.

Getter und Setter werden in vielen objektorientierten Programmiersprachen verwendet, um das Prinzip der Datenkapselung sicherzustellen (wird als Bündelung von Daten mit den Methoden angesehen, die mit diesen Daten arbeiten).

Diese Methoden sind natürlich der Getter zum Abrufen der Daten und der Setter zum Ändern der Daten.

Nach diesem Prinzip werden die Attribute einer Klasse privatisiert, um sie zu verbergen und vor anderem Code zu schützen.

Ja, @property ist im Grunde eine pythonische Methode, um Getter und Setter zu verwenden.

Python hat ein großartiges Konzept namens Eigenschaft, das das Leben eines objektorientierten Programmierers viel einfacher macht.

Nehmen wir an, Sie entscheiden sich für eine Klasse, in der die Temperatur in Grad Celsius gespeichert werden kann.

class Celsius:
def __init__(self, temperature = 0):
    self.set_temperature(temperature)

def to_fahrenheit(self):
    return (self.get_temperature() * 1.8) + 32

def get_temperature(self):
    return self._temperature

def set_temperature(self, value):
    if value < -273:
        raise ValueError("Temperature below -273 is not possible")
    self._temperature = value

Refactored Code, hier ist, wie wir es mit Eigentum erreicht haben könnten.

In Python ist property () eine integrierte Funktion, die ein Eigenschaftsobjekt erstellt und zurückgibt.

Ein Eigenschaftsobjekt verfügt über drei Methoden: getter (), setter () und delete ().

class Celsius:
def __init__(self, temperature = 0):
    self.temperature = temperature

def to_fahrenheit(self):
    return (self.temperature * 1.8) + 32

def get_temperature(self):
    print("Getting value")
    return self.temperature

def set_temperature(self, value):
    if value < -273:
        raise ValueError("Temperature below -273 is not possible")
    print("Setting value")
    self.temperature = value

temperature = property(get_temperature,set_temperature)

Hier,

temperature = property(get_temperature,set_temperature)

Hätte aufgeschlüsselt werden können als,

# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)

Zu beachtender Punkt:

  • get_temperature bleibt eine Eigenschaft anstelle einer Methode.

Jetzt können Sie durch Schreiben auf den Temperaturwert zugreifen.

C = Celsius()
C.temperature
# instead of writing C.get_temperature()

Wir können weiter gehen und die Namen get_temperature und set_temperature nicht definieren, da sie nicht erforderlich sind und den Klassennamensraum verschmutzen.

Die pythonische Methode , um mit dem oben genannten Problem umzugehen, ist die Verwendung von @property .

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    @property
    def temperature(self):
        print("Getting value")
        return self.temperature

    @temperature.setter
    def temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        print("Setting value")
        self.temperature = value

Zu beachtende Punkte -

  1. Eine Methode zum Abrufen eines Werts wird mit "@property" dekoriert.
  2. Die Methode, die als Setter fungieren muss, ist mit "@ temperatur.setter" dekoriert. Wenn die Funktion "x" genannt worden wäre, müssten wir sie mit "@ x.setter" dekorieren.
  3. Wir haben "zwei" Methoden mit demselben Namen und einer unterschiedlichen Anzahl von Parametern "def Temperatur (Selbst)" und "Def Temperatur (Selbst, x)" geschrieben.

Wie Sie sehen können, ist der Code definitiv weniger elegant.

Lassen Sie uns nun über ein reales praktisches Szenario sprechen.

Angenommen, Sie haben eine Klasse wie folgt entworfen:

class OurClass:

    def __init__(self, a):
        self.x = a


y = OurClass(10)
print(y.x)

Nehmen wir nun weiter an, dass unsere Klasse bei Kunden beliebt wurde und sie sie in ihren Programmen verwendeten. Sie haben dem Objekt alle Arten von Aufgaben zugewiesen.

Und eines schicksalhaften Tages kam ein vertrauenswürdiger Kunde zu uns und schlug vor, dass "x" ein Wert zwischen 0 und 1000 sein muss. Dies ist wirklich ein schreckliches Szenario!

Aufgrund von Eigenschaften ist es einfach: Wir erstellen eine Eigenschaftsversion von "x".

class OurClass:

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

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x

Das ist großartig, nicht wahr? Sie können mit der einfachsten Implementierung beginnen, die Sie sich vorstellen können, und Sie können später auf eine Eigenschaftsversion migrieren, ohne die Benutzeroberfläche ändern zu müssen! Eigenschaften sind also nicht nur ein Ersatz für Getter und Setter!

Sie können diese Implementierung hier überprüfen

15
Divyanshu Rawat 16 Sept. 2019 im 12:48

Eine Bemerkung: Für mich, für Python 2.x, funktionierte @property nicht wie angekündigt, als ich nicht von object geerbt habe:

class A():
    pass

Aber funktionierte wenn:

class A(object):
    pass

Für Python 3 hat immer funktioniert.

-3
sanyash 12 Mai 2019 im 08:14

Hier ist ein weiteres Beispiel:

##
## Python Properties Example
##
class GetterSetterExample( object ):
    ## Set the default value for x ( we reference it using self.x, set a value using self.x = value )
    __x = None


##
## On Class Initialization - do something... if we want..
##
def __init__( self ):
    ## Set a value to __x through the getter / setter... Since __x is defined above, this doesn't need to be set...
    self.x = 1234

    return None


##
## Define x as a property, ie a getter - All getters should have a default value arg, so I added it - it will not be passed in when setting a value, so you need to set the default here so it will be used..
##
@property
def x( self, _default = None ):
    ## I added an optional default value argument as all getters should have this - set it to the default value you want to return...
    _value = ( self.__x, _default )[ self.__x == None ]

    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Get x = ' + str( _value ) )

    ## Return the value - we are a getter afterall...
    return _value


##
## Define the setter function for x...
##
@x.setter
def x( self, _value = None ):
    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Set x = ' + str( _value ) )

    ## This is to show the setter function works.... If the value is above 0, set it to a negative value... otherwise keep it as is ( 0 is the only non-negative number, it can't be negative or positive anyway )
    if ( _value > 0 ):
        self.__x = -_value
    else:
        self.__x = _value


##
## Define the deleter function for x...
##
@x.deleter
def x( self ):
    ## Unload the assignment / data for x
    if ( self.__x != None ):
        del self.__x


##
## To String / Output Function for the class - this will show the property value for each property we add...
##
def __str__( self ):
    ## Output the x property data...
    print( '[ x ] ' + str( self.x ) )


    ## Return a new line - technically we should return a string so it can be printed where we want it, instead of printed early if _data = str( C( ) ) is used....
    return '\n'

##
##
##
_test = GetterSetterExample( )
print( _test )

## For some reason the deleter isn't being called...
del _test.x

Grundsätzlich das gleiche wie im C (Objekt) -Beispiel, außer dass ich stattdessen x verwende ... Ich initialisiere auch nicht in __init - ... nun ... das tue ich, aber es kann sein entfernt, weil __x als Teil der Klasse definiert ist ....

Die Ausgabe ist:

[ Test Class ] Set x = 1234
[ Test Class ] Get x = -1234
[ x ] -1234

Und wenn ich self.x = 1234 in init auskommentiere, lautet die Ausgabe:

[ Test Class ] Get x = None
[ x ] None

Und wenn ich in der Getter-Funktion _default = None auf _default = 0 setze (da alle Getter einen Standardwert haben sollten, dieser aber nicht von den Eigenschaftswerten übergeben wird, die ich gesehen habe, können Sie ihn hier definieren, und es ist eigentlich nicht schlecht, weil Sie den Standard einmal definieren und überall verwenden können) dh: def x (self, _default = 0):

[ Test Class ] Get x = 0
[ x ] 0

Hinweis: Die Getter-Logik dient nur dazu, den Wert von ihm manipulieren zu lassen, um sicherzustellen, dass er von ihm manipuliert wird - dasselbe gilt für die print-Anweisungen ...

Hinweis: Ich bin an Lua gewöhnt und in der Lage, mehr als 10 Helfer dynamisch zu erstellen, wenn ich eine einzelne Funktion aufrufe, und ich habe etwas Ähnliches für Python erstellt, ohne Eigenschaften zu verwenden, und es funktioniert bis zu einem gewissen Grad, aber obwohl die Funktionen zuvor erstellt wurden Bei der Verwendung gibt es manchmal immer noch Probleme, wenn sie vor ihrer Erstellung aufgerufen werden. Dies ist seltsam, da sie nicht so codiert sind. Ich bevorzuge die Flexibilität von Lua-Metatabellen und die Tatsache, dass ich tatsächliche Setter / Getter verwenden kann anstatt im Wesentlichen direkt auf eine Variable zuzugreifen ... Ich mag es, wie schnell einige Dinge mit Python erstellt werden können - zum Beispiel GUI-Programme. Obwohl eine, die ich entwerfe, ohne viele zusätzliche Bibliotheken möglicherweise nicht möglich ist - wenn ich sie in AutoHotkey codiere, kann ich direkt auf die benötigten DLL-Aufrufe zugreifen, und das Gleiche kann in Java, C #, C ++ und mehr erfolgen - vielleicht auch in mir Ich habe noch nicht das Richtige gefunden, aber für dieses Projekt kann ich von Python wechseln.

Hinweis: Die Code-Ausgabe in diesem Forum ist fehlerhaft - ich musste dem ersten Teil des Codes Leerzeichen hinzufügen, damit es funktioniert - beim Kopieren / Einfügen stellen Sie sicher, dass Sie alle Leerzeichen in Tabulatoren konvertieren. Ich verwende Tabulatoren für Python, weil in Bei einer Datei mit 10.000 Zeilen kann die Dateigröße 512 KB bis 1 MB mit Leerzeichen und 100 bis 200 KB mit Tabulatoren betragen, was einem massiven Unterschied in Bezug auf die Dateigröße und einer Verkürzung der Verarbeitungszeit entspricht.

Tabs können auch pro Benutzer angepasst werden. Wenn Sie also 2 Leerzeichen, 4, 8 oder was auch immer bevorzugen, können Sie dies für Entwickler mit Sehbehinderungen tun.

Hinweis: Alle in der Klasse definierten Funktionen werden aufgrund eines Fehlers in der Forensoftware nicht richtig eingerückt. Stellen Sie sicher, dass Sie sie beim Kopieren / Einfügen einrücken

0
Acecool 7 Aug. 2018 im 11:08

Ich habe alle Beiträge hier gelesen und festgestellt, dass wir möglicherweise ein Beispiel aus dem wirklichen Leben brauchen. Warum haben wir eigentlich @property? Stellen Sie sich also eine Flask-App vor, in der Sie das Authentifizierungssystem verwenden. Sie deklarieren einen Modellbenutzer in models.py:

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))

    ...

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

In diesem Code haben wir das Attribut password "versteckt", indem wir @property verwenden, das die Bestätigung AttributeError auslöst, wenn Sie versuchen, direkt darauf zuzugreifen, während wir @ property.setter zum Festlegen der tatsächlichen Instanz verwendet haben Variable password_hash.

Jetzt können wir in auth/views.py einen Benutzer instanziieren mit:

...
@auth.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = User(email=form.email.data,
                    username=form.username.data,
                    password=form.password.data)
        db.session.add(user)
        db.session.commit()
...

Beachten Sie das Attribut password, das aus einem Registrierungsformular stammt, wenn ein Benutzer das Formular ausfüllt. Die Kennwortbestätigung erfolgt am Frontend mit EqualTo('password', message='Passwords must match') (falls Sie sich fragen, es sich jedoch um ein anderes themenbezogenes Flask-Formular handelt).

Ich hoffe, dieses Beispiel wird nützlich sein

18
Leo Skhrnkv 10 Sept. 2019 im 15:24