我正在编写一个函数,它将元组或一对参数转换为带有int字段的namedtuple。
from collections import namedtuple
EPS = 0.00000001
def point(*cont: 'tuple or pair of args') -> namedtuple('Point', 'x y'):
"""Make an int named pair (Point)"""
if len(cont) == 1:
res = namedtuple('Point', 'x y')
if abs(int(cont[0][0])-cont[0][0]) < EPS:
res.x = int(cont[0][0])
else:
res.x = cont[0][0]
if abs(int(cont[0][1])-cont[0][1]) < EPS:
res.y = int(cont[0][1])
else:
res.y = cont[0][1]
else:
res = namedtuple('Point', 'x y')
if abs(int(cont[0])-cont[0]) < EPS:
res.x = int(cont[0])
else:
res.x = cont[0]
if abs(int(cont[1])-cont[1]) < EPS:
res.y = int(cont[1])
else:
res.y = cont[1]
return res
有更好的方法吗?
答案 0 :(得分:1)
您的代码的一个主要缺陷是它实际上并非使用 namedtuple
,您只是在namedtuple
类上设置属性。如果要将namedtuple('Point', 'x y')
替换为允许添加属性的任何其他对象,则代码的行为不会有任何不同:
>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x y')
>>> Point.x = 5
>>> Point.y = 5
>>> Point.z = 5 # uh oh
>>> Point
<class '__main__.Point'>
>>> point = Point(1, 2) # how it should work
>>> point
Point(x=1, y=2)
>>> isinstance(Point, tuple)
False
>>> isinstance(point, tuple)
True
一旦你解决了这个问题,请按照我的方式简化你的代码:
Point = namedtuple('Point', 'x y')
def maybe_floor_int(n, epsilon=0.00000001):
if abs(int(n) - n) < epsilon:
return int(n)
else:
return n
def create_point(*args: 'tuple or pair of args') -> Point:
"""Make an int named pair (Point)"""
if len(args) == 1:
x, y = args
else:
x, y = args[0]
return Point(maybe_floor_int(x), maybe_floor_int(y))
由于您的point
函数正在创建Point
元组的实例,并且您最终可能希望覆盖point
的运算符(例如能够使用乘法缩放它们) ),你也可以创建一个专门的Point
类。