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.
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__)
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)
Der erste Teil ist einfach:
@property
def x(self): ...
ist das gleiche wie
def x(self): ...
x = property(x)
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.
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'
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
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.
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
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:
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 -
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
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.
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.
@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
:
__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"
Eine Eigenschaft kann auf zwei Arten deklariert werden.
Sie können sich einige Beispiele ansehen, die ich über properties in python geschrieben habe.
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
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