Frage

Sagen, dass ich eine Klasse C bin erklärt und einige der Erklärungen sind sehr ähnlich. Ich möchte eine Funktion f verwenden Codewiederholung für diese Erklärungen zu reduzieren. Es ist möglich, nur zu erklären und verwendet f wie gewohnt:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     w = f(42)
... 
>>> C.v
'<9>'
>>> C.w
'<42>'
>>> C.f(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with C instance as first argument (got int instance instead)

Oops! Ich habe versehentlich f nach außen ausgesetzt, aber es ist kein self Argument (und kann nicht aus offensichtlichen Gründen). Eine Möglichkeit wäre, die Funktion del, nachdem ich es verwenden:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     del f
... 
>>> C.v
'<9>'
>>> C.f
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'C' has no attribute 'f'

Aber was, wenn ich will f verwenden Sie es später erneut, nach der Erklärung? Es geht nicht um die Funktion zu löschen. Ich könnte es „privater“ (das heißt, den Präfix seinen Namen mit __) und gibt ihm die @staticmethod Behandlung, aber Aufruf staticmethod Objekte durch abnorme Kanäle bekommen sehr funky:

>>> class C(object):
...     @staticmethod
...     def __f(num):
...             return '<' + str(num) + '>'
...     v = __f.__get__(1)(9)   # argument to __get__ is ignored...
... 
>>> C.v
'<9>'

Ich habe die oben Verrücktheit zu verwenden, da staticmethod Objekte, die Deskriptoren sind, sind selbst nicht aufrufbar. Ich brauche die Funktion durch den staticmethod Gegenstand gewickelt zu erholen, bevor ich es nennen kann.

Es hat doch ein besserer Weg, dies zu tun. Wie kann ich sauber eine Funktion in einer Klasse deklarieren, verwenden sie während ihrer Erklärung, und es auch später aus der Klasse verwenden? Soll ich auch das tun?

War es hilfreich?

Lösung

Ganz einfach, die Lösung ist, dass f muss kein Mitglied der Klasse sein. Ich gehe davon aus, dass Ihre Gedanken-Prozess durch eine Javaish Sprache Filter gegangen ist die mentale Blockade verursacht. Es geht ein wenig etwas wie folgt aus:

def f(n):
    return '<' + str(num) + '>'

class C(object):

    v = f(9)
    w = f(42)

Wenn Sie dann f wieder verwenden möchten, verwenden Sie es nur

>>> f(4)
'<4>'

Ich denke, die Moral von der Geschichte ist „In Python, nicht wahr Haben alles in eine Klasse zu zwingen“.

Andere Tipps

Ali A ‚s Antwort, wenn Sie wirklich wollen, f im Modul-Namensraum zu vermeiden (und einen nicht ausgeführten Namen wie _f, oder Einstellung __all__ nicht ausreichend ist), dann Sie können dies erreichen, indem die Klasse innerhalb eines Verschlusses zu schaffen.

def create_C():
    def f(num):
        return '<' + str(num) + '>'

    class C(object):
        v = f(9)
        def method_using_f(self, x):  return f(x*2)
    return C

C=create_C()
del create_C

Auf diese Weise C hat Zugriff auf f in seiner Definition und Methoden, aber nichts anderes ist (abgesehen von recht beteiligt Selbstbeobachtung seine Methoden (C.method_using_f.im_func.func_closure))

Dies ist wahrscheinlich übertrieben für die meisten Zwecke jedoch - dass f dokumentieren sollte mit der „_“ Präfix nameing Konvention intern im allgemeinen ausreichend sein.

[Bearbeiten] Eine andere Möglichkeit ist, dass Sie es in Beispiel verwenden möchten in den Verfahren einen Verweis auf die Pre-wrapped Funktion Objekt zu halten, indem er sie als Standardargument Einstellung.

class C(object):
    def f(num):
        return '<' + str(num) + '>'

    v = f(9)
    def method_using_f(self, x, f=f):  return f(x*2)

    del f

(Obwohl ich denke, dass die Schließung Ansatz ist wahrscheinlich besser)

Dies ist eine Möglichkeit:

class _C:
    # Do most of the function definitions in here
    @classmethod
    def f(cls):
        return 'boo'

class C(_C):
    # Do the subsequent decoration in here
    v = _C.f()

Ich glaube, Sie versuchen, dies zu tun:

class C():
...     class F():
...         def __call__(self,num):
...             return "<"+str(num)+">"
...     f=F()
...     v=f(9)
>>> C.v
'<9>'
>>> C.f(25)
'<25>'
>>> 

Vielleicht gibt es bessere oder pythonic Lösung ...

  

„eine Funktion in einer Klasse deklarieren, verwenden sie während ihrer Erklärung, und es auch später verwenden, um von innerhalb der Klasse“

     

Es tut uns leid. Kann nicht getan werden.

„Kann nicht getan werden“ scheint nicht mit Python auszukommen

Eine Option: Schreiben Sie eine bessere staticmethod:

class staticfunc(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kw):
        return self.func(*args, **kw)
    def __repr__(self):
        return 'staticfunc(%r)' % self.func

Lassen Sie sich von Anfang an beginnen.

„eine Funktion in einer Klasse deklarieren, verwenden sie während ihrer Erklärung, und es auch später verwenden, um von innerhalb der Klasse“

Es tut uns leid. Kann nicht getan werden. „In einer Klasse“ widerspricht „bei der Deklaration verwendet“.

  • In einer Klasse bedeutet im Rahmen der Erklärung erstellt.
  • bei der Deklaration verwendet wird, bedeutet es außerhalb der Klasse existiert. Oft als Meta-Klasse. Es gibt jedoch auch andere Möglichkeiten.

Es ist nicht klar, welche C. W und C.v sein sollen. Sind sie nur Strings? Wenn ja, eine externe Funktion f ist die beste Lösung. Die „nicht Unordnung der Namespace“ ist ein bisschen trügerisch. Schließlich wollen Sie es wieder verwenden.

Es ist im selben Modul wie C. Das ist, warum Python-Modulen hat. Es bindet die Funktion und Klasse zusammen.

import myCmod

myCmod.C.w
myCmod.C.v
myCmod.f(42)

Wenn w und v sind nicht einfache Strings, gibt es eine sehr gute Lösung, die viel Flexibilität.

Im Allgemeinen ist für Klasse-Ebene ( „statisch“) Variablen wie diese, können wir andere Klassen verwenden. Es ist nicht möglich, vollständig die gewünschte API zu erreichen, aber das ist in der Nähe.

>>> class F(object):
    def __init__( self, num ):
        self.value= num
        self.format= "<%d>" % ( num, )

>>> class C(object):
    w= F(42)
    v= F(9)

>>> C.w
<__main__.F object at 0x00C58C30>
>>> C.w.format
'<42>'
>>> C.v.format
'<9>'

Der Vorteil hierbei ist, dass F eine richtige, erstklassige Sache, die verlängert werden kann. Nicht eine „versteckte“ Sache, die wir versuchen, auszusetzen zu vermeiden. Es ist eine Tatsache des Lebens, so könnten wir das Open / Closed Prinzip auch folgen und es zu Erweiterung machen öffnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top