将自定义类设为该类方法的可选参数类型
简而言之:
我想知道如何把一个可选参数的类型设置为我自己创建的类,也就是:
代码:
class Point(object):
def __init__(self,x=int,y=int): # Initialize Point object with optional args
self.val=(x,y)
def __add__(self,p=Point): # p=Point is the issue
...
我试过:
def __add__(self,p=self.__class__): # Cannot reference self in an arg.
def __add__(self,p=Point): # Point is not defined
长话短说:
我搜索了很多,但到现在为止没有找到答案,我觉得可能是我用的词不对。
我正在创建一个二维点/向量类(我知道,这个已经有人做过了,但我在学习,也在发展我的写作风格)。我对在大多数情况下使用没有类型的参数有些反感,主要是为了方便维护。
我一直没能弄明白如何把一个可选参数的类型设置为我自己创建的类,比如上面的 Point,而不是 Python 内置的类型。
注意:我知道把 p 设置为一个位置参数是可行的,确实可以,但只要没有特别的理由不这样做,除了这对 Python 的哲学来说有点僵硬,我还是想给参数加上类型,以便让代码更清晰。
这怎么能实现?这样做值得吗?这样做有没有什么缺点?
如果有关于这类事情的最佳实践建议,我会非常欢迎。
3 个回答
Gabriel的回答是对的,但这可能不是你想要的结果。
关于你看到的实际问题:这和内置类型和自定义类型没有关系。问题在于,默认参数是在函数定义的时候就被计算的,但一个类要等到类的定义结束后才算存在。所以你不能在自己的类体内把Point
当作默认参数,因为在那个时候,Point
还不存在呢!
如果我是你,我会创建一个新的类来继承元组,这样做:
>>> class Point(tuple):
... def __new__ (cls, x, y):
... return super(Point, cls).__new__(cls, (x,y))
... def __init__(self, x, y):
... super(Point, self).__init__(x,y)
... self.x=int(x)
... self.y=int(y)
... def __add__(self,point_add):
... if len(point_add) != 2:
... exit("Not a coordinate")
... new_x = self.x + int(point_add[0])
... new_y = self.y + int(point_add[1])
... new_point = self.__new__(Point, new_x, new_y)
... new_point.x = new_x
... new_point.y = new_y
... return new_point
...
>>> p_a = Point(1, 2)
>>> p_b = Point(1, 2)
>>> p_c = p_a + p_b
>>> print "tuple:", p_c
tuple: (2, 4)
>>> print "x:", p_c.x, "y:", p_c.y
x: 2 y: 4
>>>
这样你就可以把点当作元组来使用,同时在某种程度上也可以把元组当作点来用。上面提到的 __add__()
方法可以用来加一个元组或者一个点。
我觉得你可能误解了代码中的 x=int
和 y=int
的作用。
class Point(object):
def __init__(self,x=int,y=int): # Initialize Point object with optional args
...
def __add__(self,p=Point):
创建一个 Point
的实例,
u = Point()
会生成一个对象 u
。可选参数 x
和 y
实际上是指向表示 int
类型的 Python 对象,而不是具体的整数(这里要区分整数,比如 1、3、99 和它们的类型 int
)。一般来说,在函数参数中使用等号是为了指定一个默认值,而不是类型。同样,如果没有传递参数 p
给函数 add
,那么 p
将等于表示 Point
类的对象。这并不会让 p
成为 Point
类的一个实例。你不能提前指定函数参数的类型。此外,它们的类型可以在函数内部改变。这是因为 Python 是一种动态类型的语言。
这篇关于鸭子类型的 页面 可能会帮助你更好地理解。如果你愿意,可以在参数传入后检查它们的类型,并根据这些信息进行操作,但基本的想法是,如果它的表现像一个 int
,说话也像一个 int
,那么它的实际类型是 int
又有什么关系呢。
鸭子类型文章的 Python 部分会描述 Python 中的异常 及其在这些情况下的建议用法。