Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从另一个命名元组推断命名元组或将其子类型化?_Python_Python 2.7_Dto_Namedtuple_Python Attrs - Fatal编程技术网

Python 如何从另一个命名元组推断命名元组或将其子类型化?

Python 如何从另一个命名元组推断命名元组或将其子类型化?,python,python-2.7,dto,namedtuple,python-attrs,Python,Python 2.7,Dto,Namedtuple,Python Attrs,前言 我想知道如何以python的方式概念化数据类。 具体来说,我指的是DTO(.) 我在@jeff oneill question“”中找到了一个很好的答案,其中@joe kington很好地使用了内置的namedtuple 问题 在Python2.7文档的第8.3.4节中,介绍了如何组合多个命名元组。 我的问题是如何实现相反的效果 示例 考虑到文件中的示例: >>> p._fields # view the field names ('x', 'y')

前言

我想知道如何以python的方式概念化数据类。 具体来说,我指的是DTO(.)

我在@jeff oneill question“”中找到了一个很好的答案,其中@joe kington很好地使用了内置的
namedtuple

问题

在Python2.7文档的第8.3.4节中,介绍了如何组合多个命名元组。 我的问题是如何实现相反的效果

示例

考虑到文件中的示例:

>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)
如何从“像素”实例推断“颜色”或“点”实例


最好是pythonic spirit.

Point.\u fields+Color.\u fields
只是一个元组。鉴于此:

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
Color = namedtuple('Color', 'red green blue')
Pixel = namedtuple('Pixel', Point._fields + Color._fields)

f = Point._fields + Color._fields
type(f)
只是
tuple
。因此,没有办法知道它是从哪里来的

我建议您研究如何轻松处理属性对象。这将允许您进行适当的继承,并避免定义访问字段的所有好方法的开销

所以你可以

import attr

@attr.s
class Point:
    x, y = attr.ib(), attr.ib()

@attr.s
class Color:
    red, green, blue = attr.ib(), attr.ib(), attr.ib()

class Pixel(Point, Color):
    pass

现在,
Pixel.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。顺便说一下,如果您经常需要此操作,可以基于
像素创建
颜色插件
函数。甚至对于任何子名称的倍数

from collections import namedtuple

Point = namedtuple('Point', 'x y')
Color = namedtuple('Color', 'red green blue')
Pixel = namedtuple('Pixel', Point._fields + Color._fields)

pixel_ins = Pixel(x=11, y=22, red=128, green=255, blue=0)
color_ins = Color._make(getattr(pixel_ins, field) for field in Color._fields)

print color_ins
输出:
颜色(红色=128,绿色=255,蓝色=0)

用于提取任意子名称的函数(无错误处理):


这里是Nikolay Prokopyev的
提取子名称双倍
的替代实现,它使用字典而不是
getattr

from collections import namedtuple

Point = namedtuple('Point', 'x y')
Color = namedtuple('Color', 'red green blue')
Pixel = namedtuple('Pixel', Point._fields + Color._fields)

def extract_sub_namedtuple(tup, subtype):
    d = tup._asdict()
    return subtype(**{k:d[k] for k in subtype._fields})

pix = Pixel(11, 22, 128, 255, 0)

point = extract_sub_namedtuple(pix, Point)
color = extract_sub_namedtuple(pix, Color)
print(point, color)
输出

Point(x=11, y=22) Color(red=128, green=255, blue=0)
这可以写成一行:

def extract_sub_namedtuple(tup, subtype):
    return subtype(**{k:tup._asdict()[k] for k in subtype._fields})
但是它的效率较低,因为它必须为
子类型中的每个字段调用
tup.\u asdict()
。\u fields

当然,对于这些特定的namedtuple,您可以

point = Point(*pix[:2])
color = Color(*pix[2:])
但这不是很优雅,因为它硬编码父字段的位置和长度


FWIW,有代码可以将多个namedtuple组合成一个namedtuple,保留字段顺序并跳过重复的字段。

另一种方法是使“Pixel”的参数与您实际需要的对齐,而不是展平其组成部分的所有参数

我认为你应该有两个参数:位置和颜色。这两个字段可以用其他元组初始化,而不必进行任何推断

例如:

#代替像素(x=11,y=22,红色=128,绿色=255,蓝色=0)
像素=像素(点(x=11,y=22),颜色(红色=128,绿色=255,蓝色=0))
#获取像素参数化的命名元组
像素颜色=像素颜色
像素点=像素位置
通过将所有参数混合在一起(例如,主对象上的x、y、红色、绿色和蓝色),您实际上没有获得任何东西,但会丢失很多易读性。如果namedtuple参数共享字段,则展平参数也会引入错误:

从集合导入namedtuple
Point=namedtuple('Point',['x','y']))
Color=namedtuple('Color','red-green-blue')
色调=命名倍数('Hue','red-green-blue')
像素=命名倍数('Pixel',Point.\u字段+颜色.\u字段+色调.\u字段)
#结果:
#回溯(最近一次呼叫最后一次):
#文件“”,第1行,在
#文件“C:\Program Files\Python38\lib\collections\\uuuuu init\uuuuu.py”,第370行,在namedtuple中
#raise VALUERROR(f'遇到重复的字段名:{name!r}')
#ValueError:遇到重复的字段名:“红色”

背景

最初我问这个问题是因为我必须支持一些意大利面代码库,它经常使用元组,但没有对元组中的值给出任何解释。 经过一些重构之后,我注意到我需要从其他元组中提取一些类型化信息,并且正在寻找一些无样板文件和类型安全的方法来实现这一点

解决方案

您可以将命名的tuple definition子类化,并实现一个自定义的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。有关更多详细信息,请参见此

示例

from\uuuuu future\uuuuu导入注释
从集合导入namedtuple
输入importunion,Tuple
点=命名的整数('Point','xy')
Color=namedtuple('Color','red-green-blue')
像素=命名倍数('Pixel',Point.\u字段+颜色.\u字段)
#重新声明“颜色”以提供自定义创建方法
#可以从各种不同类型中推断出值
班级颜色(颜色):
def uu new uu(cls,*主题:联合[像素,颜色,元组[浮点,浮点,浮点])->颜色:
#如果只得到一个类型为“Pixel”或“Color”的参数
如果len(subject)=1且isinstance((it:=subject[0]),(像素,颜色)):
#从无效的颜色属性创建
返回super()
else:#else将其视为原始值,并在无效后对其进行旁路
返回super()
@类方法
def invalidate(cls,r,g,b)->Tuple[float,float,float]:
#将值转换为浮点值
r、 g,b=(在(r,g,b)中为它浮动(it))
#确保所有值都在有效范围内
断言所有(0>(0.0,0.5,1.0)=颜色==来自\u颜色==来自\u像素
真的

你的意思是你想把一个名为“像素”的
拆分成一个
点和一个
颜色的
吗?不完全拆分,但能够实例化“颜色”或“点”,同时只拥有一个“像素”的实例,如可接受的答案所示。好的。你可能对
point = Point(*pix[:2])
color = Color(*pix[2:])