如何重载基于参数types的__init__方法?

比方说,我有一个类,有一个名为数据的成员,这是一个列表。

我想能够初始化类,例如,一个文件名(包含数据初始化列表)或与一个实际的列表。

你做这个的技术是什么?

你只是通过查看__class__检查types吗?

有什么我可能会错过的技巧吗?

我习惯了C ++,通过参数types重载很容易。

获得“替代构造函数”的更简单的方法是使用类方法。 例如:

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

它的更好的原因是毫无疑问,预期什么types,你不必被猜测的调用者打算为你做的数据types,它给你。 isinstance(x, basestring)是调用者没有办法告诉你,例如,即使这个types不是一个basestring,你应该把它当作一个string(而不是另一个序列)。也许调用者希望为不同的目的使用相同的types,有时作为一个单一的项目,有时作为一系列的项目。 明确表示会让所有的疑问消失,并导致更强大和更清晰的代码。

很好的问题。 我也解决了这个问题,虽然我同意“工厂”(类方法构造函数)是一个好方法,但是我想提出另一个方法,我也发现它非常有用:

下面是一个示例(这是一个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") 

并从string中读取,我说:

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

这样用户只需一个方法即可。 正如你所看到的,处理它并不是太复杂

更好的方法是使用isinstance和types转换。 如果我正确地理解你,你想这样做:

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

快速和肮脏的修复

 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 

那么你可以打电话给它

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

你应该使用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.). 

你可能想要内置的内置函数:

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

我的首选解决scheme是:

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

你为什么不去更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?