Frage

Lassen Sie uns sagen, dass ich eine Klasse, die ein Mitglied hat Daten genannt, die eine Liste ist.

Ich möchte in der Lage, die Klasse mit, zum Beispiel zu initialisieren, einen Dateinamen (die Daten enthält, um die Liste zu initialisieren) oder mit einer aktuellen Liste.

Was ist Ihre Technik, dies zu tun?

Kontrollieren Sie, nur die Art von an __class__ suchen?

Gibt es einen Trick, den ich fehlen könnte?

Ich bin zu C ++ verwendet, wo durch das Argument Typ Überlastung ist einfach.

War es hilfreich?

Lösung

Eine viel ordentliche Art und Weise "alternative Konstrukteurs zu bekommen, ist Class zu verwenden. Zum Beispiel:

>>> class MyData:
...     def __init__(self, data):
...         "Initialize MyData from a sequence"
...         self.data = data
...     
...     @classmethod
...     def fromfilename(cls, filename):
...         "Initialize MyData from a file"
...         data = open(filename).readlines()
...         return cls(data)
...     
...     @classmethod
...     def fromdict(cls, datadict):
...         "Initialize MyData from a dict's items"
...         return cls(datadict.items())
... 
>>> MyData([1, 2, 3]).data
[1, 2, 3]
>>> MyData.fromfilename("/tmp/foobar").data
['foo\n', 'bar\n', 'baz\n']
>>> MyData.fromdict({"spam": "ham"}).data
[('spam', 'ham')]

Der Grund, es ordentlicheres ist, dass es keinen Zweifel ist, welche Art zu erwarten ist, und Sie sind nicht auf das, was der Anrufer soll erraten gezwungen, für Sie mit dem Datentyp tun, es Ihnen gab. Das Problem mit isinstance(x, basestring) ist, dass es keine Möglichkeit für den Anrufer, Ihnen zu sagen, zum Beispiel, dass, obwohl der Typ kein basestring ist, können Sie es als String behandeln sollte (und nicht eine andere Sequenz.) Und vielleicht würde der Anrufer möchte die gleiche Art für verschiedene Zwecke, manchmal als ein einzelnes Element, und manchmal als eine Folge von Elementen zu verwenden. Als explizit alle Zweifel weg nimmt und führt zu robusteren und klarem Code.

Andere Tipps

Ausgezeichnete Frage. Ich habe auch dieses Problem in Angriff genommen, und während ich, dass „Fabriken“ (Klasse-Methode Bauer) vereinbaren eine gute Methode sind, würde Ich mag eine andere vorschlagen, die ich auch sehr nützlich gefunden habe:

Hier ist eine Probe (dies ist eine read Methode und kein Konstruktor, aber die Idee ist die gleiche):

def read(self, str=None, filename=None, addr=0):
    """ Read binary data and return a store object. The data
        store is also saved in the interal 'data' attribute.

        The data can either be taken from a string (str 
        argument) or a file (provide a filename, which will 
        be read in binary mode). If both are provided, the str 
        will be used. If neither is provided, an ArgumentError 
        is raised.
    """
    if str is None:
        if filename is None:
            raise ArgumentError('Please supply a string or a filename')

        file = open(filename, 'rb')
        str = file.read()
        file.close()
    ...
    ... # rest of code

Die zentrale Idee hier ist, unter Verwendung von Python eine hervorragende Unterstützung für benannte Argumente, dies umzusetzen. Nun, wenn ich die Daten aus einer Datei lesen will, sage ich:

obj.read(filename="blob.txt")

Und es aus einem String zu lesen, sage ich:

obj.read(str="\x34\x55")

Auf diese Weise der Benutzer nur eine einzige Methode hat zu rufen. es in der Handhabung, wie Sie sahen nicht allzu komplex

quick and dirty fix

class MyData:
    def __init__(string=None,list=None):
        if string is not None:
            #do stuff
        elif list is not None:
            #do other stuff
        else:
            #make data empty

Dann rufen Sie können es mit

MyData(astring)
MyData(None, alist)
MyData()

Eine bessere Möglichkeit wäre isinstance und Typumwandlung zu verwenden. Wenn ich Sie recht bin zu verstehen, wollen Sie diese:

def __init__ (self, filename):
    if isinstance (filename, basestring):
        # filename is a string
    else:
        # try to convert to a list
        self.path = list (filename)

mit python3, können Sie Implementieren von mehreren Versand mit Funktion Anmerkungen als Python-Kochbuch schrieb:

import time


class Date(metaclass=MultipleMeta):
    def __init__(self, year:int, month:int, day:int):
        self.year = year
        self.month = month
        self.day = day

    def __init__(self):
        t = time.localtime()
        self.__init__(t.tm_year, t.tm_mon, t.tm_mday)

und es funktioniert wie:

>>> d = Date(2012, 12, 21)
>>> d.year
2012
>>> e = Date()
>>> e.year
2018

Sie sollten verwenden isinstance

isinstance(...)
    isinstance(object, class-or-type-or-tuple) -> bool

    Return whether an object is an instance of a class or of a subclass thereof.
    With a type as second argument, return whether that is the object's type.
    The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
    isinstance(x, A) or isinstance(x, B) or ... (etc.).

Sie wollen wahrscheinlich die isinstance gebautet Funktion:

self.data = data if isinstance(data, list) else self.parse(data)

Meine bevorzugte Lösung ist:

class MyClass:
    _data = []
    __init__(self,data=None):
        # do init stuff
        if not data: return
        self._data = list(data) # list() copies the list, instead of pointing to it.

aufrufen Dann ist es entweder mit MyClass() oder MyClass([1,2,3]).

Ich hoffe, das hilft. Glücklich Coding!

OK, groß. Ich warf nur zusammen, um dieses Beispiel mit einem Tupel, keinen Dateinamen, aber das ist einfach. Vielen Dank an Alle.

class MyData:
    def __init__(self, data):
        self.myList = []
        if isinstance(data, tuple):
            for i in data:
                self.myList.append(i)
        else:
            self.myList = data

    def GetData(self):
        print self.myList

a = [1,2]

b = (2,3)

c = MyData (a)

d = MyData (b)

c.GetData ()

d.GetData ()

[1, 2]

[2, 3]

Warum Sie nicht einmal mehr pythonic gehen?

class AutoList:
def __init__(self, inp):
    try:                        ## Assume an opened-file...
        self.data = inp.read()
    except AttributeError:
        try:                    ## Assume an existent filename...
            with open(inp, 'r') as fd:
                self.data = fd.read()
        except:
            self.data = inp     ## Who cares what that might be?
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top