我是一个完全“静态类型”的人,并且是python的初学者,我想在python中创建数据类型,以保存某些对象的上一个-下一个状态。结构是这样的:
class PrevCurr:
def __init__(self, obj_initial):
self.previous = obj_initial
self.current = obj_initial
没问题,如果我obj_initial
是[None, None]
这样的。但是想象一下,我需要将该类包装到不同的大类型上,例如1000种以上的字典/列表/集合或/和用户定义的类。然后,我想要这样的东西:
class PrevCurr:
def __init__(self, obj_type, *args, **kwargs):
'''make self.previous and self.orientation of the same type as obj_type'''
self.previous = ...
self.current = ...
我的问题是:如何确定将字段(或python中是否有其他名称?)设置为与要包装到的对象相同的类型?我上面有个想法,我可以通过某种方式将类型和有关此类型的其他信息(例如大小等)作为参数而不是对象本身来传递,以节省内存,但是然后如何确保将我的字段设置为与对象完全相同的类型?我无法在python中将构造函数作为参数传递,并且在python中找不到用于该任务的任何通用编程。否则我的想法完全错误。
您正在思考,就像使用C或Java这样的静态类型的语言一样,在这种语言中,您必须为特定类型的对象预先分配内存,然后再为其分配任何内容。这是python中的错误方法。
相反,让我们考虑一下您想要什么:一个可以表示任何单一类型,但是一旦初始化的类只能表示该特定类型的类。在Java中,您可以为此使用泛型,但是python没有这些。我们在python中可以做的是确保只能将正确类型的对象分配给它。
如果程序员不正确地使用该类,则在python中这样做的惯用方法是在运行时引发错误。静态类型检查器实际上并没有抛出Java那样好的编译时错误的好方法。我提出以下内容供您考虑:
class PrevCurr:
@property
def previous(self):
return self._previous
@previous.setter
def previous(self, value):
if not isinstance(value, self._type):
raise ValueError(f"Previous value must be of type {self._type}")
self._previous = value
@property
def current(self):
return self._current
@current.setter
def current(self, value):
if not isinstance(value, self._type):
raise ValueError(f"Current value must be of type {self._type}")
self._current = value
def __init__(self, obj_initial):
self._type = type(obj_initial)
self._previous = obj_initial
self._current = obj_initial
在这里,我们有两个面向外部的变量:previous
和和current
您在当前示例中一样。因为我们想要设置这些变量的特定行为,所以我们使用@property
装饰器对其进行声明。它们的实际值分别保存在“专用”变量_previous
和中_current
。
初始化后,我们检查初始对象的类型,并将该类型作为'private'变量存储到类中_type
。
然后,每次(甚至类的实例本身)尝试设置instance.previous
或时instance.current
,我们都会将其重定向到适当的函数。在此函数中,我们检查要设置的对象是否与初始化类时使用的类型相同。如果没有,我们抛出一个错误。
例如,如果要存储列表或其他集合,那么我认为没有任何合理的方法可以确保整个列表保持相同的类型(或者实际上对列表的内容进行任何假设),因为python本身不是。它们都是<type 'list'>
)。
一种可能的解决方法是使用元类并重写__instancecheck__()
metaclass方法,以创建dict
仅包含特定类型对象的子类,然后PrevCurr
使用其中之一来初始化您的实例。
我从类的名称假定您有一些方法.update()
可以将该current
值复制到previous
,并分配一个current
必须是相同类型的新值。在这种情况下,您可能需要使用getter和setter来直接进行分配previous
。
用法示例:
>>> a = PrevCurr(3)
>>> a.previous = 2
>>> a.previous = 4.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in previous
ValueError: Previous value must be of type <class 'int'>
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句