Python中的类并定义属性类型

时间:2017-02-14 09:25:38

标签: python

我是Python新手,对Python 2.6中的类及其属性有疑问。

假设我有一个类Node,就像这样:

class Node:
    x = int
    y = int
    neighbours = []
    discovered = bool
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def setNeigbours(self,neighbours):
        self.neighbours = neighbours

    def addNeighbours(self,n):
        if type(n) == list:
            self.neighbours.extend(n)
        else:
            self.neighbours.append(n)

    def isDiscovered(self):
        return self.discovered

    def setDiscovered(self,discovered):
        self.discovered = discovered

这样的Graph类:

class Graph:
    nodeList = Node
    edgeList = Edge

    def __init__(self,nodeList,edgeList):
        self.edgeList = edgeList
        self.nodeList = nodeList

    def getNodes(self):
        return self.nodeList

    def setNodes(self,nodeList):
        self.nodeList = nodeList

    def addNode(self,n):
        if type(n) == list:
            self.nodeList.extend(n)
        else:
            self.nodeList.append(n)

如果我现在创建一个新图并添加一些节点:

n1 = Node(0,0)
n2 = Node(1,1)
g = Graph([],[])
g.addNode(n1)
g.addNode(n2)

我希望以下print <Type 'Node'>

for n in g.nodeList:
    print type(n)

但是当我运行它时,我得到了:

<type 'instance'>
<type 'instance'>

有没有办法告诉Python,nodeList是一个列表,只包含Node - 元素?

4 个答案:

答案 0 :(得分:1)

确实有,如果您使用的是最新版本的Python(在撰写本文时为3.6.0)。

from typing import List

class Graph:
    nodeList: List[Node]

Python本身实际上不会对信息做任何事情,但是有一些Python的类型检查工具会执行静态分析并告诉您是否尝试在列表中添加Node之外的其他内容

对于旧版本的Python 3,您可以使用fomatted注释执行类似操作,然后类型检查工具将能够执行相同的检查:

from typing import List

class Graph:
    nodeList  # type: List[Node]

所有这些当然只在运行程序之前提供可选的静态类型检查。一旦你的代码运行,Python就不会关心对象的类型,只要它们具有正确的方法和属性:如果它像鸭子一样嘎嘎叫Python将它视为鸭子。

如果您想了解有关Python中可选静态类型检查的更多信息,请参阅http://mypy-lang.org/

打印Node类型的实例为您提供<type 'instance'>这一事实表明您正在使用某些版本的Python 2.如果可能的话,请考虑切换到更新的版本,但是至少如果你想继续使用Python 2,请确保所有对象都明确地来自object

class Node(object):
   ...

如果您这样做,print语句将显示该课程。如果不这样做,那么从Python的早期开始就会为你提供旧式的类,你会发现像属性这样的东西无法正常使用它们。

答案 1 :(得分:0)

这就是你编写Python的方式;它看起来像Java。

您不需要在班级“声明”属性;这样做的唯一原因是使用在所有实例之间共享的值,这些值您没有这样做,因为您会立即使用实例属性覆盖它们。删除这些定义。

编写getter和setter方法也非常简单,特别是如果它们只返回属性。您的调用代码应直接访问属性。

关于你的问题,因为你使用的是Python 2 [*],你的类必须从object继承。如果你这样做,你会看到正确的类型:

class Graph(object):
   ...

g = Graph()
type(g) # module.Graph

(*)注意,你真的一定不能用2.6;它已过时且不受支持。如果你坚持2.x至少使用2.7;但实际上你应该使用3.x,除了其他任何东西之外,它还会修复你原来的问题。

答案 2 :(得分:0)

由于Python是动态类型的,因此无法在Python中强制执行类型。

可能的解决方案是在运行时检查实例类型。

首先,从object继承你的班级(即新的&#39;对象):

class Node(object):
   # your code here

class Graph(object):
   # your code here

然后你可以在运行时进行类型检查:

>>> g = Graph()
>>> type(g)
<class '__main__.Graph'>
>>> isinstance(g, Graph)
True

答案 3 :(得分:0)

Python是动态类型语言。在使用变量之前不需要声明变量,也不需要声明它们的类型。

你可以这样做:

foo = 1 # this is an integer
foo = "string" # this is a string

变量foo将包含存储在其中的值的类型。

在Python中,您可以在同一个列表中存储不同类型的对象,如果您只想强制存储一种类型,则可以对内置的list类进行子类化。