如何为python自定义类进行类型转换
考虑一个类如何为python自定义类进行类型转换,python,class,python-2.7,casting,Python,Class,Python 2.7,Casting,考虑一个类 class temp: def __init__(self): pass 我把它当作目标 obj = temp() 将其转换为字符串 strObj = str(obj) 现在,如何将strObj转换为temp类的对象 org = temp(strObj) 正如Anand在评论中所指出的,您需要的是对象序列化和反序列化。实现这一点的一种方法是通过pickle(或cPickle)模块: 导入pickle >>>类示例(): ... 定义初始化(se
class temp:
def __init__(self):
pass
我把它当作目标
obj = temp()
将其转换为字符串
strObj = str(obj)
现在,如何将strObj转换为temp类的对象
org = temp(strObj)
正如Anand在评论中所指出的,您需要的是对象序列化和反序列化。实现这一点的一种方法是通过pickle(或cPickle)模块: 导入pickle >>>类示例(): ... 定义初始化(self,x): ... self.x=x ... >>>a=示例('foo') >>>astr=pickle.dumps(a)#(i_uuumain_uu\n例如\np0\n(dp1\nS'x'\np2\nS'foo'\np3\nsb)。 >>>b=酸洗负荷(应力应变率) >>>b >>>b.x “福”
但是,请注意,使用pickle模块时遇到的一个问题是处理实现版本。正如Python文档中所建议的,如果您希望一个未经pickle的实例自动处理实现版本控制,则可能需要添加一个version实例属性并添加一个自定义的_usetstate__;实现:。否则,ob的版本无论对对象本身所做的代码更改如何,序列化时的对象将与反序列化时的对象完全相同。对于那些希望覆盖转换内置项的人,例如
int(obj)
,float(obj)
,和str(obj)
,请参见。您需要在对象上实现\uuuu int\uuuuuuu
、\uuuu float\uuuuu
或\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu str
。要回答这个问题,一种方法是结合使用“滥用”。让我们首先看看\uuu repr\uuuucode>文档(重点:我的):
由repr()内置函数调用以计算“官方”
对象的字符串表示形式。如果可能,应该
看起来像一个有效的Python表达式,可以用来重新创建
对象具有相同的值(给定适当的环境)。如果
是不可能的,一个字符串的形式
应返回。返回值必须是字符串对象。如果
类定义了\uuuuu repr\uuuuu()
但不定义\uuuu str\uuuuuu()
,那么\uuuuuu repr\uuuuuu()
也是
当该实例的“非正式”字符串表示形式时使用
课程是必修的
这通常用于调试,因此
表示是信息丰富且明确的
考虑到这一点,我们知道建议从\uuuu repr\uuuu
返回一个字符串,该字符串可以与eval()
一起使用。这一点可以通过以下语句得到暗示:值“应该看起来像一个有效的Python表达式”
例子
下面是一个使用此方法的示例。该示例也覆盖了\uuuuueq\uuuuuu
,但只是为了方便打印输出。为了完整性,我们还向该实例添加了一个值
该示例创建一个新实例。然后使用\uuuu repr\uuu
将该值转换为字符串(通过使用该函数。接下来,该字符串值将被传递给该字符串,该字符串将计算该字符串并返回结果。结果将是同一类的新实例,并存储在second\u instance
中。我们还打印了该函数,以可视化我们确实有两个不同的实例。最后,我们显示first\u instance==second\u instance
确实是正确的
:
class MyClass:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(self, MyClass) and self.value == other.value
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)
first_instance = MyClass(123)
print('First instance: repr=%r, id=%d' % (first_instance, id(first_instance)))
stringified = repr(first_instance)
print('Stringified: %r' % stringified)
second_instance = eval(stringified) # !!! DANGEROUS (see below) !!!
print('Second instance: repr=%r, id=%d' % (second_instance, id(second_instance)))
print('First == Second: %r' % (first_instance == second_instance))
什么时候可以这样做?
如果进入eval()
的所有内容都在您的控制之下,则这是100%可接受的!这意味着:
- 调用
eval()
的范围在您的控制之下
- 计算字符串中的任何位置都不应包含来自外部源的数据。外部源包括:
- 数据库值
- 用户输入
- 从磁盘读取的数据
- …基本上是任何I/O
记住所有这些,并保证在项目的未来任何时候I/O都不会以eval()
调用结束,这几乎是不可能的。因此,我强烈建议在重要的生产代码中避免这种情况,因为它会打开严重的安全漏洞
对于不在生产环境中运行的代码,这是绝对可以接受的。例如,单元测试、个人实用程序脚本、e.t.c。但应始终考虑风险
为什么这很危险?
- 传递到
eval()
的代码在调用它的Python进程内以相同的权限执行。例如:您从多个用户都可以访问的数据库中读取一个值,然后eval()
它。在这种情况下,另一个用户可以通过数据库注入代码,该代码将作为您的用户运行
- 当值来自外部源时,使用
eval()
打开了代码注入的可能性
- 不能保证
repr()
将返回有效的Python表达式。这只是文档的建议。因此,使用\uuu repr\uuu
调用eval
很容易出现运行时错误
- 在上面的示例中,调用
eval()
的作用域需要“了解”类MyClass
(必须导入)。它只查找名称。因此,如果纯粹出于偶然,作用域中存在相同的名称,但指向另一个对象,您将无意中调用其他对象,并可能会遇到奇怪的错误。当然,这是一个边缘情况
更安全的选择
使用许多可用序列化选项中的一个。最常用也是最简单的一个选项是将对象转换为JSON字符串或从JSON字符串转换为JSON字符串。上面的示例可以像这样安全:
import json
class MyClass:
@staticmethod
def from_json(document):
data = json.loads(document)
instance = MyClass(data['value'])
return instance
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(self, MyClass) and self.value == other.value
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)
def to_json(self):
data = {
'value': self.value
}
return json.dumps(data)
first_instance = MyClass(123)
print('First instance: repr=%r, id=%d' % (first_instance, id(first_instance)))
stringified = first_instance.to_json()
print('Stringified: %r' % stringified)
second_instance = MyClass.from_json(stringified)
print('Second instance: repr=%r, id=%d' % (second_instance, id(second_instance)))
print('First == Second: %r' % (first_instance == second_instance))
这只是稍微困难一点,但要安全得多
同样的方法也可用于其他序列化方法。流行的格式有:
- (请注意,这使用字节而不是文本作为序列化介质)
- (请注意,这使用字节而不是文本作为序列化介质)
- 自定义实现
如果根据传递的参数类型定义类构造函数会怎么样
import json
class MyClass:
@staticmethod
def from_json(document):
data = json.loads(document)
instance = MyClass(data['value'])
return instance
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(self, MyClass) and self.value == other.value
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.value)
def to_json(self):
data = {
'value': self.value
}
return json.dumps(data)
first_instance = MyClass(123)
print('First instance: repr=%r, id=%d' % (first_instance, id(first_instance)))
stringified = first_instance.to_json()
print('Stringified: %r' % stringified)
second_instance = MyClass.from_json(stringified)
print('Second instance: repr=%r, id=%d' % (second_instance, id(second_instance)))
print('First == Second: %r' % (first_instance == second_instance))
class temp():
def __init__(self, *args):
if len(args) > 0:
if isinstance(args[0],str):
self.attr = args[0]
else:
self.attr = 'Not a string'
else:
self.attr = 'Not a string'
def __str__(self):
return self.attr
obj = temp()
obj.attr = 'Hello World'
strObj = str(obj)
org = temp(strObj)
class obj():
def __init__(self, attribs*):
if len(attribs)==1 and type(attribs[0])=='str':
#your string manipulations go here
self.content = attribs[0].upper()