python類別方法




如何重載基於參數類型的__init__方法? (7)

你應該使用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.).

假設我有一個有名為data的成員的類,它是一個列表。

我希望能夠使用例如文件名(包含要初始化列表的數據)或實際列表來初始化類。

你做這個的技術是什麼?

你只是通過查看__class__檢查類型嗎?

有什麼我可能會錯過的技巧嗎?

我習慣於C ++,它通過參數類型重載很容易。


你為什麼不去更pythonic?

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?

太好了。 我只是把這個例子與一個元組一起拋出,而不是一個文件名,但這很容易。 謝謝大家。

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]


很好的問題。 我也解決了這個問題,雖然我同意“工廠”(類方法構造函數)是一個好方法,但我想推薦另一個方法,我也發現它非常有用:

下面是一個示例(這是一個read方法,而不是構造函數,但其思路是相同的):

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

關鍵的想法是使用Python對命名參數的出色支持來實現這一點。 現在,如果我想從文件中讀取數據,我會說:

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

並從字符串中讀取它,我說:

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

這樣用戶只需調用一個方法。 正如你所看到的那樣處理它並不太複雜


您可能需要使用isinstance內置函數:

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

我的首選解決方案是:

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.

然後用MyClass()MyClass([1,2,3])調用它。

希望有所幫助。 快樂編碼!


獲得'替代構造函數'的更簡單的方法是使用類方法。 例如:

>>> 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')]

它更簡潔的原因是毫無疑問預期的是什麼類型,並且你不會被迫猜測調用者打算如何處理它給你的數據類型。 isinstance(x, basestring)在於,調用者無法告訴您,例如,即使該類型不是基礎字符串,也應該將其視為字符串(而不是另一個序列)。也許調用者希望為不同的目的使用相同的類型,有時作為單個項目,有時候作為一系列項目。 明確表示會帶來一切疑慮,並導致更強大和更清晰的代碼。





operator-overloading