如何在Python中创建强类型对象引用?
我刚开始接触Python 2.7。
我想在一个类和另一个类之间建立一种强类型的引用。
假设我有两个类:
class Module:
count = 0
def __init__(self, m_name, m_type, m_on=False):
self.name = m_name
self.type = m_type
self.on = m_on
self.id = self.count
self.count += 1
还有一个叫做Slot
的类,我想在里面放一个Module
作为元素:
class Slot:
count = 0
def __init__(self):
self.id = self.count
self.count += 1
self.element = None
现在我想添加一个方法,用来设置这个Slot
里的element
,然后在其他方法中使用它(包括它的字段和方法),但我想确保这个元素是Module
类型。
如果我能让PyCharm知道element
是Module
类型,那就更好了,这样它可以自动补全我输入的内容。
这可能吗?除了在初始化方法中这样做,我还能用其他方法让Python识别吗:
self.element = Module()
(如果我这样做,它会把element
识别为Module
类型,并且会自动补全)。
2 个回答
我想你说的是静态类型引用,而不是强类型引用。其实,Python 的引用是强类型的。
如果你想要静态类型,那 Python 可能不太适合你。
我也觉得这个说法没有什么特别的地方:
self.element = Module()
这只是创建了一个 Module 类的对象。而且,变量 'element' 的类型仍然是 Module 类,除非你明确地把它重新赋值为其他类型。
这和我们在 C++ 或 Java 中做的事情不太一样,但我认为这种灵活性让 Python 更加强大。
希望这些能帮到你。
正如haraprasadj所说,Python 不是静态类型的,所以你可能需要适应这种情况,并相应地编写代码。Python 和 Java 不一样。我是从 Java 转过来的,刚开始的时候我也花了一些时间来适应这些东西,但一旦你习惯了,你会发现 Java 的语法显得过于“挑剔”和繁琐(嗯……至少我现在是这么觉得的)。
说到这一点,使用新风格类(从object
继承的类),你可以使用@property
装饰器来创建透明的获取器和设置器(可以参考这个问题、这个问题和这个文档)。
在你的情况下,为了确保Slot
类的element
属性总是None
或者是Module
的实例,你可以这样做:
class Module(object):
count = 0
def __init__(self, m_name, m_type, m_on=False):
self.name = m_name
self.type = m_type
self.on = m_on
self.id = self.count
self.count += 1
class Slot(object):
count = 0
def __init__(self):
self.id = self.count
self.count += 1
self.element = None
@property
def element(self):
return self._element
@element.setter
def element(self, e):
if not(e is None or isinstance(e, Module)):
raise TypeError("Element must be None or Module")
self._element = e
if __name__ == "__main__":
s = Slot()
m = Module('name', 'type')
print "s.element? %s" % s.element
s.element = m
print "s.element? %s" % s.element
# Now, exception:
s.element = "hellouuuu"
这段代码的输出是:
s.element? None
s.element? <__main__.Module object at 0x26c9b10>
Traceback (most recent call last):
File "./stack13.py", line 35, in <module>
s.element = "hellouuuu"
File "./stack13.py", line 25, in element
raise TypeError("Element must be None or Module")
TypeError: Element must be None or Module
那么,这里发生了什么呢?当你创建一个Slot
的实例(变量s
),并尝试通过s.module = "whatever"
给它的module
属性赋值时,实际上调用的是s
的@element.setter
方法,参数e
的值是"whatever"
。如果这个方法没有抛出异常,实际的属性会存储在s._module
中。你可以使用vars(s)
来查看这个类的实际属性(关于vars
的更多信息可以参考这里):
>> s = Slot()
>> m = Module('name', 'type')
>> s.element = m
>> print "%s" % vars(s)
{'count': 1, 'id': 0, '_element': <__main__.Module object at 0x19d0b10>}
看到了吗?那里没有element
,只有_element
。
现在,当你尝试读取element
属性时,使用s.element
,实际上是调用了用@property
装饰的方法。
在我发的例子中,在那个方法里加一个print
语句:
@property
def element(self):
print "I'm reading self._element. Wohooo"
return self._element
现在,重新执行脚本。你会在输出中看到:
I'm reading self._element. Wohooo
s.element? None
I'm reading self._element. Wohooo
s.element? <__main__.Module object at 0x1fd0ad0>
{'count': 1, 'id': 0, '_element': <__main__.Module object at 0x1fd0ad0>}
Traceback (most recent call last):
File "./stack13.py", line 37, in <module>
s.element = "hellouuuu"
File "./stack13.py", line 26, in element
raise TypeError("Element must be None or Module")
TypeError: Element must be None or Module