某些Python类(如float
)可以解析字符串以创建对象:
number_string = "4.5"
assert float(number_string) == 4.5
技术上是什么?用字符串构造函数调用?但是如果构造函数也会为常规对象构造(而不是字符串)采用其他参数呢?
如何实现一个可以解析字符串以创建实例的类?
添加:
看起来float(str)
正在调用传递的字符串的__float__
特殊方法 - 字符串知道其float
值。
实现__float__
的每个对象都可以传递给float(obj)
:
>>> class MyClass:
... def __float__(self):
... return 0.01
...
>>> m = MyClass()
>>> float(m)
0.01
此方法仅适用于特定类型(如float
和int
)的转换,因为转换实际上发生在传递的对象中。我想要的是相反的地方,转换发生在传递字符串的对象中。我认为Paul McCGuire建议的静态parse
方法可能是一个很好的解决方法。
答案 0 :(得分:3)
这是一个带字符串的构造函数调用。如果你有一个构造函数需要超过字符串值,那么你可以定义一个classmethod工厂方法,它接受一个字符串,从中提取其他数据(但你已经编码),然后用所有必要的args调用构造函数。 @tiagoboldt引用了这个类定义:
class Student(object):
def __init__ (self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
我会添加此方法以接受“name / age / gender”形式的字符串:
@classmethod
def parse(cls, s):
# some input validation here would be a good idea
name,age,gender = s.split('/')
age = int(age)
return cls(name, age, gender)
s1 = Student("Bob", 10, "M")
s2 = Student.parse("Bill/12/M")
答案 1 :(得分:2)
这只是根据类型处理不同参数的一般情况。通常认为测试类型的形式不好,除非绝对必要,但Python有type()
和isinstance()
是有原因的!
你会注意到dict()
构造函数可以获取现有的字典对象,键/值对的元组列表(或其他可迭代的)或关键字参数(它们作为字典到达构造函数,但是作为选项1)的不同论点。在Java或其他静态类型语言中,这些都是不同的构造方法。但在Python中,任何类型都可以在任何参数中传递。只有一个构造函数(或初始化程序)。
因此dict
类型必须在其__init__()
方法中有一些智能来处理dict或列表作为第一个参数,还有一个可选的关键字参数。两者都必须是可选的。它的实现方式如下:
class dict(object):
def __init__(self, d={}, **kwd):
if isinstance(d, type(self)):
self.update(d)
else:
for i in d:
self[i[0]] = i[1]
self.update(kwd)
(使用自己类型的对象定义一个类是有问题的,所以我确定我写的内容实际上不会运行,除了dict
实际上是用C实现的,但你希望得到想法。)
在您自己的对象中,您可以使某些参数成为可选参数,并根据传入的内容测试必要的参数类型,以便对它们进行不同的处理。如果您希望能够处理字符串,则可以使用{{ 1}}在Python 2.x中(所以测试匹配常规字符串和Unicode字符串)或者仅仅是Python 3中的isinstance(arg, basestring)
。
Paul建议的工厂类方法也不是一个坏主意,特别是对于可以以多种方式执行初始化的类。我会将这些方法命名为isinstance(arg, str)
等。
答案 2 :(得分:1)
class MyObject(object):
def __init__(self, data):
super(MyObject,self).__init__()
if isinstance(data, self.__class__): # copy constructor
self.value = data.value
elif isinstance(data, basestring):
self.value = float(data) # parse string
else:
self.value = data
并在使用中:
a = MyObject(3.9) # a.value = 3.9
b = MyObject("3.9") # string constructor - b.value = 3.9
c = MyObject(a) # copy constructor - c.value = 3.9
答案 3 :(得分:-1)
你正在做的是一个演员。从字符串实现构造函数的最佳方法是使用 init 方法并将字符串传递给它。
一个更复杂的例子(不只是一个字符串):http://www.java2s.com/Code/Python/Class/Averysimpleclasswithaconstructor.htm