it-swarm.com.de

Wie funktioniert der @property-Dekorateur?

Ich würde gerne verstehen, wie die eingebaute Funktion property funktioniert. Was mich verwirrt, ist, dass property auch als Dekorateur verwendet werden kann. Es sind jedoch nur Argumente erforderlich, wenn sie als integrierte Funktion und nicht als Dekorateur verwendet werden.

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 Dekorator 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 Dekorateure x.setter und x.deleter erstellt? Ich bin verwirrt.

745
ashim

Die Funktion property() gibt ein spezielles Descriptor-Objekt zurück :

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

Dieses Objekt verfügt über extra -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 als Dekorateure auch. Sie geben ein neues Eigenschaftsobjekt zurück:

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

das ist eine Kopie des alten Objekts, jedoch mit einer der Funktionen ersetzt.

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

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

bedeutet eigentlich dasselbe wie

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

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

Mit der folgenden Sequenz wird auch eine Full-On-Eigenschaft erstellt, indem diese Dekorationsmethoden verwendet werden.

Zuerst erstellen wir einige Funktionen und ein property-Objekt mit 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 .deleter()-Methode hinzu:

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

Nicht zuletzt fungiert das property-Objekt als Descriptor-Objekt , so dass es .__get__() , .__set__() und .__delete__() Methoden zum Einhaken in das Instanzattribut holen, setzen und löschen hat:

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

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

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__)
811
Martijn Pieters

Dokumentation sagt es ist nur eine Verknüpfung zum Erstellen von Readonly-Eigenschaften. So

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

ist äquivalent zu

def getx(self):
    return self._x
x = property(getx)
121
J0HN

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 einer property mit nur einem Getter.

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

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

gibt eine neue Eigenschaft zurück, die alles von der alten x plus dem angegebenen Setzer erbt.

x.deleter arbeitet genauso.

71
glglgl

Hier ist ein minimales Beispiel, 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'

Ansonsten 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'
64
AlexG

Diese folgende:

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
34
Bill Moore

Nachfolgend finden Sie ein weiteres Beispiel, wie @property helfen kann, wenn Code geändert werden muss, der aus here stammt (ich fasse ihn 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 abhängig von dieser Klasse, in der er/sie verwendet, 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 an, Sie entscheiden sich dafür, Ihre Money-Klasse zu ändern und die dollars- und cents-Attribute zu entfernen, stattdessen entscheiden Sie sich, nur die Gesamtmenge der Cents zu verfolgen:

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

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

money = Money(27, 12)

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

es wird ein Fehler angezeigt

AttributeError: 'Money'-Objekt hat kein Attribut' Dollars '

Das bedeutet, dass jetzt jeder, der auf Ihre ursprüngliche Money-Klasse angewiesen ist, alle Codezeilen ändern muss, in denen dollars und cents verwendet werden, was sehr schmerzhaft sein kann ... Wie kann 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 funktioniert wie erwartet und wir mussten keine einzige Codezeile in unserer Bibliothek ändern! In der Tat müssten wir nicht einmal wissen, dass sich die Bibliothek, von der wir abhängig sind, verändert hat.

Auch die 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.
18
Cleb

Ich habe alle Beiträge hier gelesen und festgestellt, dass wir ein Beispiel aus dem wirklichen Leben brauchen können. Warum haben wir eigentlich @property? Betrachten Sie eine Flask-App, bei der Sie ein Authentifizierungssystem verwenden. Sie deklarieren einen Modellbenutzer in models.py:

class User(UserMixin, db.Model):
    __table= '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 mit Hilfe von @property "verborgen", wodurch AttributeError-Assertion ausgelöst wird, wenn Sie versuchen, direkt auf es zuzugreifen, während wir mit @ property.setter die tatsächliche Instanzvariable password_hash setzen.

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

...
@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, aber es handelt sich um ein anderes Thema, das sich auf Flaschenformulare bezieht).

Ich hoffe, dieses Beispiel wird nützlich sein 

12
Leo Skhrnkv

Beginnen wir mit Python-Dekorateuren.

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

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

Betrachten Sie den folgenden Codeausschnitt.

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 kann man sagen, dass die Decorator-Funktion unsere say_hello-Funktion modifiziert und 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 schließen als mit einem Fallszenario, aber davor wollen wir über ein paar Oops-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 verstanden, die auf diese Daten zugreifen).

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 als privat gekennzeichnet, um sie vor anderem Code zu verbergen und zu schützen.

Yup, @property ist im Grunde eine Pythonic-Methode, um Getter und Setter zu verwenden.

Python hat ein großartiges Konzept, das als Eigenschaft bezeichnet wird und das Leben eines objektorientierten Programmierers wesentlich vereinfacht.

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, So hätten wir es mit Eigentum erreichen können.

In Python ist property () eine integrierte Funktion, die ein Eigenschaftenobjekt 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 als gebrochen werden können,

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

Hinweis zu beachten:

  • get_temperature bleibt eine Eigenschaft anstelle einer Methode.

Jetzt können Sie den Temperaturwert durch Schreiben abrufen.

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

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

Der Pythonic-Weg, der sich mit dem obigen Problem befasst, 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

Punkte zu beachten -

  1. Eine Methode, die zum Abrufen eines Werts verwendet wird, ist mit "@property" versehen.
  2. Die Methode, die als Setzer fungieren soll, ist mit "@ temperature.setter" dekoriert. Wenn die Funktion "x" heißen würde, müssten wir sie mit "@ x.setter" dekorieren.
  3. Wir haben "zwei" Methoden mit demselben Namen und einer unterschiedlichen Anzahl von Parametern "def temperature (self)" und "def temperature (self, x)" geschrieben.

Wie Sie sehen, ist der Code definitiv weniger elegant.

Lassen Sie uns nun über eine praktische Szene 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 weiter an, dass unsere Klasse bei Kunden populär wurde und sie anfingen, sie in ihren Programmen zu verwenden. Sie haben dem Objekt alle möglichen Aufgaben zugewiesen.

Und an einem schicksalhaften Tag kam ein vertrauenswürdiger Kunde zu uns und schlug vor, dass "x" einen Wert zwischen 0 und 1000 haben muss. Dies ist wirklich ein schreckliches Szenario!

Aufgrund der 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 denkbar einfachsten Implementierung beginnen, und Sie können später zu einer 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 überprüfen hier

5
Divyanshu Rawat

Dieser Punkt wurde von vielen Leuten dort oben geklärt, aber hier ist ein direkter Punkt, den ich gesucht habe .. Dies ist, was ich für wichtig halte, mit dem @property-Dekorateur zu beginnen.

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

Der Aufruf der Funktion "get_config ()" wird so funktionieren.

util = UtilityMixin()
print(util.get_config)

Wenn Sie feststellen, dass ich die Klammern "()" nicht für den Aufruf der Funktion verwendet habe. Dies ist die grundlegende Sache, die ich nach dem @property-Dekorateur gesucht habe. Damit Sie Ihre Funktion wie eine Variable nutzen können.

5
Devendra Bhat

property ist eine Klasse hinter @property decorator.

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)

Es gibt keinen Unterschied, wie wir die Eigenschaft verwenden, wie Sie sehen können.

Um die Frage zu beantworten, 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__ müssen überschrieben sein. Dies ist die Implementierung des Deskriptormusters in Python.

Im Allgemeinen ist ein Deskriptor ein Objektattribut mit „Bindungsverhalten“, dessen Attributzugriff von Methoden im Deskriptorprotokoll überschrieben wurde.

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

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"
1
prosti

Eine Eigenschaft kann auf zwei Arten deklariert werden.

  • Erstellen der Getter-Setter-Methoden für ein Attribut und Übergeben dieser als Argument an die Funktion property
  • Verwenden des Dekorators @property.

Sie können sich einige Beispiele ansehen, die ich über properties in python geschrieben habe. 

1
nvd

Hier ist ein anderes 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

Im Grunde dasselbe wie das C (object) -Beispiel, außer dass ich stattdessen x verwende ... Ich initialisiere auch nicht in __init - ... naja ... ich tue es, aber es kann wegen __x entfernt werden ist als Teil der Klasse definiert ....

Die Ausgabe ist:

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

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

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

und wenn ich _default = None auf _default = 0 in der Getter-Funktion gesetzt habe (da alle Getter einen Standardwert haben sollten, diese aber nicht von den Eigenschaftswerten der zuvor genannten Informationen übergeben werden, können Sie sie hier definieren, und Es ist eigentlich nicht schlecht, weil Sie den Standardwert einmal definieren und überall verwenden können. Beispiel: def x (self, _default = 0):

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

Hinweis: Die Getter-Logik dient nur dazu, dass der Wert von ihm manipuliert wird, um sicherzustellen, dass er von ihm manipuliert wird. Gleiches gilt für die Druckanweisungen.

Hinweis: Ich bin es gewohnt, Lua zu verwenden und in der Lage zu sein, dynamisch 10+ Helfer zu erstellen, wenn ich eine einzelne Funktion aufrufe. Ich habe etwas Ähnliches für Python gemacht, ohne Eigenschaften zu verwenden. Das funktioniert bis zu einem gewissen Grad, obwohl die Funktionen zuvor erstellt wurden Wenn sie verwendet werden, gibt es manchmal Probleme, dass sie vor dem Erstellen aufgerufen werden, was seltsam ist, 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 ich eines entwerfe, kann es ohne viele zusätzliche Bibliotheken nicht möglich sein - wenn ich es in AutoHotkey codiere, kann ich direkt auf die benötigten DLL-Aufrufe zugreifen, und das Gleiche kann in Java, C #, C++ und mehr geschehen - vielleicht auch ich 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 er funktioniert. Beim Kopieren/Einfügen müssen Sie alle Leerzeichen in Tabulatoren konvertieren. Ich verwende Tabulatoren für Python, weil in Eine Datei mit 10.000 Zeilen und einer Dateigröße kann zwischen 512 KB und 1 MB mit Leerzeichen und zwischen 100 und 200 KB mit Registerkarten liegen. Dies entspricht einem massiven Unterschied bei der Dateigröße und einer Reduzierung der Verarbeitungszeit ...

Tabs können auch für jeden Benutzer angepasst werden. Wenn Sie also 2 Felder bevorzugen, 4, 8 oder was auch immer Sie tun können, bedeutet dies, dass es für Entwickler mit Sehschwächen nachdenklich ist.

Hinweis: Alle in der Klasse definierten Funktionen werden aufgrund eines Fehlers in der Forensoftware nicht ordnungsgemäß eingerückt. Stellen Sie sicher, dass Sie sie einrücken, wenn Sie kopieren/einfügen

1
Acecool

Eine Bemerkung: Für mich, für Python 2.x, funktionierte @property nicht wie angekündigt, als ich das Formularobjekt nicht erbte:

class A():
    pass

aber gearbeitet, wenn:

class A(object):
    pass

für Pyhton 3 hat immer gearbeitet

0