我正在尝试list()在课堂上打电话时返回一个列表.什么是最好的方法.
class Test():
def __init__(self):
self.data = [1,2,3]
def aslist(self):
return self.data
a = Test()
list(a)
[1,2,3]
Run Code Online (Sandbox Code Playgroud)
我想要什么时候list(a)调用它来运行该aslist函数,理想情况下我想实现asdict它在dict()调用时有效
我希望能够与做到这一点dict,int和所有其他类型转换
与您可能习惯的许多其他语言(例如,C++)不同,Python没有"类型转换"或"转换运算符"或类似的任何概念.
相反,Python类型的构造函数通常被编写为一些更通用的(duck-typed)协议.
首先要做的是找到你关心的构造函数的文档,看看它想要什么.从内置函数开始,即使它们中的大多数都会将您链接到内置类型中的条目.
其中许多将链接到数据模型章节中相关特殊方法的条目.
例如,int说:
...如果x定义
__int__(),则int(x)返回x.__int__().如果x定义__trunc__(),则返回x.__trunc__()...
然后你可以点击链接__int__,虽然在这种情况下没有太多额外的信息:
调用实现内置函数complex(),int()和float().应该返回适当类型的值.
所以,你想要定义一个__int__方法,它应该返回一个int:
class MySpecialZero:
def __int__(self):
return 0
Run Code Online (Sandbox Code Playgroud)
的顺序和设置类型(如list,tuple,set,frozenset)是有点复杂.他们都想要一个可迭代的:
能够一次返回其成员的对象.iterables的实例包括所有类型的序列(如
list,str,和tuple)和一些非序列类型,如dict,文件对象,你用定义任何类的对象__iter__()方法或与__getitem__()实现序列语义方法.
在iter功能下对此进行了更好的解释,这可能不是最明显的看法:
... 对象必须是支持迭代协议(
__iter__()方法)的集合对象,或者它必须支持序列协议(__getitem__()从0开始的整数参数的方法)...
而下__iter__的数据模型:
当容器需要迭代器时,将调用此方法.此方法应返回一个新的迭代器对象,该对象可以迭代容器中的所有对象.对于映射,它应该迭代容器的键.
Iterator对象也需要实现此方法; 他们被要求归还自己.有关迭代器对象的更多信息,请参阅迭代器类型.
因此,对于您的示例,您希望成为一个迭代元素的对象self.data,这意味着您需要一个__iter__返回这些元素的迭代器的方法.要做到这一点最简单的方法是只叫iter上self.data-或者,如果你想有aslist其他原因的方法,也许叫iter上什么方法将返回:
class Test():
def __init__(self):
self.data = [1,2,3]
def aslist(self):
return self.data
def __iter__(self):
return iter(self.aslist())
Run Code Online (Sandbox Code Playgroud)
请注意,正如Edward Minnix所解释的那样,Iterator和Iterable是分开的东西.Iterable是在调用其__iter__方法时可以生成Iterator的东西.所有迭代器都是Iterables(它们自己生成),但许多Iterables不是迭代器(例如list,序列).
dict(OrderedDict等)也有点复杂.检查文档,你会发现它想要一个映射(即类似a的东西dict)或一个可迭代的键值对(这些对本身就是迭代).在这种情况下,除非您实现完整映射,否则您可能需要回退:
class Dictable:
def __init__(self):
self.names, self.values = ['a', 'b', 'c'], [1, 2, 3]
def __iter__(self):
return zip(self.names, self.values)
Run Code Online (Sandbox Code Playgroud)
几乎一切是容易的,就像int-但是请注意str,bytes和bytearray有序列.
同时,如果您希望您的对象可以转换为a int或a list或a set,则可能希望它在其他方面也可以像其他对象一样.如果是这种情况,请查看collections.abc并且numbers,不提供不仅是抽象基类的帮助程序(如果需要检查某些类型是否满足某些协议,则使用),还有mixins(用于帮助您实现协议).
例如,一个full Sequence应该提供大多数相同的方法tuple- 大约7个 - 但是如果你使用mixin,你只需要自己定义2:
class MySeq(collections.abc.Sequence):
def __init__(self, iterable):
self.data = tuple(iterable)
def __getitem__(self, idx):
return self.data[idx]
def __len__(self):
return len(self.data)
Run Code Online (Sandbox Code Playgroud)
现在你MySeq几乎可以在任何地方使用tuple- 包括list从中构建一个,当然.
对于某些类型的,喜欢MutableSequence的快捷键帮助更-你得到的5价格17种方法.
如果你想让同一个对象可以列表并且可以直接...那么你就会遇到设计的限制.list想要一个可迭代的.dict想要一个可迭代的对,或一个映射 - 这是一种可迭代的.所以,而不是无限的选择,你只有两个:
__getitem__使用这些键实现dict,因此list给出了这些键的列表.dict,因此list给出了这些键值对的列表.显然,如果你想真正表现得像一个Mapping,你只有一个选择,第一个.
序列和映射协议重叠的事实从一开始就是Python的一部分,固有的事实是你可以[]在它们两个上使用运算符,并且保留了每一个重大变化,即使它具有其他功能(像整个ABC模型)更复杂.我不知道是否有人给出了理由,但据推测它与扩展切片设计的原因相似.换句话说,使dicts和其他映射更容易和更易读使用是值得的,使它们变得更复杂,实现更不灵活.
| 归档时间: |
|
| 查看次数: |
501 次 |
| 最近记录: |