2016-05-19 13 views
4

So habe ich einigen Gott verlassen Legacy-Code, der das reservierte Wort falsch property, um verwendet. In einer Basisklasse, die vererbt wird, wurden sie grundsätzlich implementiert.Missbrauch von Eigentum reservierten Wort

class TestClass(object): 

    def __init__(self, property): 
     self._property = property 

    @property 
    def property(self): 
     return self._property 


test = TestClass('test property') 
print(test.property) 

Welche läuft ohne Fehler. Wenn Sie eine andere Methode, die unten hinzufügen, dass Sie erhalten,

class TestClass2(object): 

    def __init__(self, property): 
     self._property = property 

    @property 
    def property(self): 
     return self._property 

    @property 
    def other_property(self): 
     return 'test other property' 


test = TestClass2('test property') 
print(test.property) 
print(test.other_property) 

Welche wirft:

---> 10  @property 
    11  def other_property(self): 
    12   print('test other property') 

TypeError: 'property' object is not callable 

Weil Sie wissen, dass Sie property im lokalen Namespace überschrieben haben.

class TestClass3(object): 

    def __init__(self, property): 
     self._property = property 

    @property 
    def other_property(self): 
     return 'test other property' 

    @property 
    def property(self): 
     return self._property 


test = TestClass3('test property') 
print(test.property) 
print(test.other_property) 

Sie können dieses Problem umgehen, wenn Sie immer Ihre property Überschreiben am Ende der Klasse definieren. Wenn die property-Methode nur für die Basisklasse definiert ist, die Sie von Dingen erben, funktioniert das auch, weil Namespaces.

class TestClass4(TestClass): 

    def __init__(self, property): 
     super(TestClass4, self).__init__(property) 

    @property 
    def other_property(self): 
     return 'test other property' 


test = TestClass4('test property') 
print(test.property) 
print(test.other_property) 

Meine Entrüstung sagt, dass wir diese Variablennamen in der riesigen Menge von Legacy-Code aktualisieren muss, weil GAAAAH, aber anders als neue Methoden zu erinnern, die über der Definition von property Definition in der selten modifizierte Base hinzufügen Klasse, das bricht eigentlich nichts richtig?

Antwort

4

nicht Schatten builtins ... fast ohne Refactoring auf alles, was Sie ganz BuiltIn Abschattung vermeiden

Verwendung __getattr__ statt @property Ihr _property Mitglied zurückzukehren ...

class TestClass(object): 
    def __init__(self): 
     self._property = 12 

    def __getattr__(self,item): 
     if item == "property": 
      #do your original getter code for `property` here ... 
      # now you have not overwritten the property keyword at all 
      return getattr(self,"_property") # just return the variable 
class TestClass2(TestClass): 
    def __init__(self): 
     self._property = 67 

print TestClass2().property 

class MySubClass(TestClass): 
    @property 
    def a_property(self): 
     return 5 

print MySubClass().property 
print MySubClass().a_property 

wirklich nebenbei bemerkt gibt es keinen guten Grund, in Python zu verwenden. alles was dazu führt ist, andere Programmierer später zu verwirren und die Tatsache zu verdecken, dass Sie tatsächlich eine Funktion aufrufen. Ich habe es regelmäßig getan ... Ich vermeide es jetzt, es sei denn, ich habe einen sehr sehr zwingenden Grund, nicht zu

+0

downvoter Grund? Ich bin ok mit einem Downvote, aber ich bin neugierig, warum? –

+0

Es gibt viele Gründe, Eigentum zu verwenden. Es ist ziemlich pythonisch, Ihre API über Attribute anstatt über Zugriffsmethoden und Mutatoren zu offenbaren, aber das würde bedeuten, dass Sie Werte nicht träge berechnen können oder Nebenwirkungen haben, wenn Leute Werte setzen. 'Eigenschaft' ermöglicht es Ihnen, das Beste aus beiden Welten zu haben. –

+1

es gibt keine privaten Variablen in Python ... und alles, was ich sagte, war eine Meinung, ich halte ihn sicherlich nicht davon ab, Eigentum zu verwenden ... meine Meinung ist ziemlich irrelevant zu meiner Antwort, die die richtige Antwort auf die Frage ist. –

0

Sie könnten immer property auf einen anderen Namen neu zuordnen. Solange Sie einen Namen wählen, der nicht mit Ihren anderen Klassenattributen übereinstimmt, und er wird nicht in der externen Schnittstelle für die Klasse verfügbar gemacht, so ist es nicht wirklich wichtig, wie Sie ihn benennen. bricht

tproperty = property 

class Test(...) 

    @tproperty 
    def property(self): 
     .... 
+2

Wenn also jemand eine Variable 'list' benannt hat, würde man empfehlen,' tlist' die ursprüngliche 'list' zuzuordnen und' tlist (x) 'ally statt' list (x) '? –

+0

Nein, verwenden Sie einfach '[]' anstelle von 'list()' :) Aber ernsthaft, Sie können sich * immer * nicht dafür einsetzen, eine API zu brechen, selbst wenn die Namensentscheidungen sehr schlecht waren. Wenn das OP mit dem Brechen der API gut war, hätte er die Frage nicht gestellt, er hätte nur den Namen geändert. Das Neuabbilden eines Built-Ins ist nicht ungewöhnlich, und es ist sicherlich vorzuziehen, einen riesigen Kommentar zu haben, der besagt: "Diese Funktion muss in der Klassendefinition der letzte sein". –

3

Ja, wenn Sie immer über die Definition des property Methode nichts neue Methoden hinzufügen. Setzen Sie also im Code einen schönen, großen Kommentar zu diesem Effekt. Hoffentlich jemand außer Kraft zu setzen property in einer abgeleiteten Klasse will zunächst an der Basisklasse suchen und Ihren Kommentar sehen ...

BTW, die property arg auf die __init__ Methode auch Schatten property, aber ich denke, das ist kein Problem.

Idealerweise sollte jemand reinigen dieses Chaos, aber ich verstehe, dass es nicht kosteneffektiv sein kann, das zu tun.

Auch bin ich etwas verwirrt, warum der ursprüngliche Codierer property ein @property in erster Linie gemacht.Dieses Konstrukt sollte nur verwendet werden, wenn der Wert des Attributs dynamisch berechnet werden muss und nicht einfach ein statisches Attribut zurückgegeben wird. Vielleicht waren sie neu in Python und ihnen wurde gesagt, dass das die Art ist, in Python getter zu machen ...

+0

meh das lokale Shadowing ist nicht eine große Sache, es sei denn, er plant Refactoring ... aber +1 für refactor nicht Schatten Builtins: P –

+0

Mann, dass Kommentar keinen Sinn machte ... Ich muss müde sein, ich meinte "... es sei denn Er plant, neue Klassen in diesem lokalen Bereich zu erstellen. " –

+0

Danke für die Beantwortung meiner Frage. Ich akzeptiere die andere Antwort, weil sie einen schönen Vorschlag zum Entfernen des Schattens hat. – TristanMatthews

Verwandte Themen