切片是 Python 中最迷人最强大最 Amazing 的语言特性(几乎没有之一),在《Python进阶:切片的误区与高级用法》中,我介绍了切片的基础用法、高级用法以及一些使用误区。...1、魔术方法:__getitem__() 想要使自定义对象支持切片语法并不难,只需要在定义类的时候给它实现魔术方法 __getitem__() 即可。所以,这里就先介绍一下这个方法。...概括翻译一下:__getitem__() 方法用于返回参数 key 所对应的值,这个 key 可以是整型数值和切片对象,并且支持负数索引;如果 key 不是以上两种类型,就会抛 TypeError;如果索引越界...下面的就是一个代表性的错误示例: ###略去其它代码#### def __getitem__(self, index): cls = type(self) if isinstance(index...4、小结 本文介绍了__getitem__()魔术方法,并用于实现自定义对象(以列表类型和字典类型为例)的切片功能,希望对你有所帮助。
那怎么判断一个对象是否可迭代呢?为什么它们是可迭代的呢?怎么让一个对象可迭代呢?...如上图蓝圈所示,普通可迭代对象与迭代器的最关键区别可概括为:一同两不同 ,所谓“一同”,即两者都是可迭代的(__iter__),所谓“两不同”,即可迭代对象在转化为迭代器后,它会丢失一些属性(__getitem...4.2、迭代器切片 前面提到了“一同两不同”,最后的不同是,普通可迭代对象在转化成迭代器的过程中会丢失一些属性,其中关键的属性是 __getitem__ 。...在前一节中,我已经介绍了这个魔术方法,并用它实现了自定义对象的切片特性。 那么问题来了:为啥迭代器不继承这个属性呢?...其次,若强行给迭代器加上这个属性,这并不合理,正所谓强扭的瓜不甜…… 由此,新的问题来了:既然会丢失这么重要的属性(还包括其它未标识的属性),为什么还要使用迭代器呢?
大家好,又见面了,我是你们的朋友全栈君。...目录 1.看源码 2、重写默认的default函数,实现自己的序列化机制 3、把对象转化成字典 3.1 __dict__的方式 3.2、定义keys和__getitem__的方式 4、最终的代码实现 5...发现如上图所示,并没有进入jsonify的default方法里,而是直接把字典给序列化出来了。 那么什么时候会调用default呢?...我们想到了对象的__dict__内置方法,但是发现没有得到任何的结果,输出的是一个空的json对象。 这是因为我们在hehe类里面定义的是类的变量而不是实例的变量。...default函数是被递归调用的,之所以我们没看到被递归调用是因为我们定义的类都太简单了,如果对象下面的某个属性是另外一个对象的情况 只要遇到不能序列化的对象,都会传入default里面让我们来解决,
我曾概括过两者的差别是“一同两不同”:相同的是都可惰性迭代,不同的是可迭代对象不支持自遍历(即next()方法),而迭代器本身不支持切片(即__getitem__() 方法)。...现在微妙之处就在于,为什么给 5 种内置方法都设计了迭代器,偏偏给 range() 方法设计的就是可迭代对象呢?把它们都统一起来,不是更好么?...以上是我对“为什么range()不产生迭代器”的一种解答。顺着这个思路,我研究了一下它产生的 range 对象,一研究就发现,这个 range 对象也并不简单。...TypeError: unsupported operand type(s) for *: 'range' and 'int' 那么问题来了:同样是不可变序列,为什么字符串和元组就支持上述两种操作,而偏偏...4、小结 回顾全文,我得到了两个偏冷门的结论:range 是可迭代对象而不是迭代器;range 对象是不可变的等差序列。 若单纯看结论的话,你也许没有感触,或许还会说这没啥了不得啊。
本文中用到的代码示例,可以在我的github下载到。 构造和初始化 __init__我们很熟悉了,它在对象初始化的时候调用,我们一般将它理解为"构造函数"....不管对象的某个属性是否存在,它都允许你为该属性进行赋值,因此你可以为属性的值进行自定义操作。有一点需要注意,实现__setattr__时要避免"无限递归"的错误,下面的代码示例中会提到。...在面向对象编程时,如果一个类的属性有相互依赖的关系时,使用描述器来编写代码可以很巧妙的组织逻辑。...可能有的人会想,list_[thing]为什么不是相当于list_[int(thing)]呢? 通过实现Thing的__int__方法能否达到这个目的呢? 显然不能。...你可能会问, 为什么不是命名为__bool__? 我也不知道。 我只知道该方法在Python3中改名为__bool__了。 __dir__(self) 对实例使用dir()时调用。
今天我们来介绍下 iter() 方法另外的用法。 据说很少有人知道这个用法 一、上代码、学用法 我们都比较熟悉 iter(obj),会返现一个迭代器,如果 obj 不是可迭代对象,则会报错。...翻译:如果没有第二个参数,object(即第一个参数)是一个支持迭代器协议(实现__iter__()方法的)的集合对象,或者是支持序列协议(实现__getitem__()方法)且是从0开始索引。...如果它不支持其中任何一个,则抛出 TypeError 异常 简单来说就是,如果没有第二个参数,就是我们比较熟悉的用法。...翻译:如果给定了第二个参数 sentinel,object 则必须是一个可调用对象,这个可调用对象没有任何参数,当可调用对象的返回值等于 sentinel 的值时,抛出 StopIteration 的异常...,返回的都是迭代器 2、iter() 方法第一个参数的参数类型,根据有无第二个参数决定 你点的每个赞,我都认真当成了喜欢
大家好,又见面了,我是你们的朋友全栈君。...TypeError: ‘NoneType’ object is not subscriptable 迭代 DataLoader时出现以下错误,暂时不知道怎么解决,向大家求救,是一个比较稀罕的错误,也分享给大家一个奇葩的问题一起讨论...: 'NoneType' object is not subscriptable 用pycharm查询过变量内容,dataloader里边的内容是没有问题的,就是迭代的时候有问题。...dataloader代码是这些 dataset = ListDataset(train_path, augment=True, multiscale=opt.multiscale_training...解决方案 数据导入时少给了数据的标签,导致数据没有标签,也就没有下标。 给了标签后,上面那个Error也可以设置多个num_workers了。
☑ __getitem__(self, key):这个方法返回与所给的键对应的值。...""" if not isinstance(key, (int, long)): raise TypeError if key < 0: raise...客户代码(使用代码的代码)应该能够用同样的方式对待所有特性。 那么怎么解决呢?把所有的属性都放到访问器方法中?这当然没问题。但如果有很多简单的特性,那么就很不现实了(有点笨)。...实际上在Python中有两种创建属性的机制。我主要讨论新的机制——只在新式类中使用的property函数,然后我会简单地说明一下如何使用特殊方法实现属性。...然而如果没有引发TypeError,那么内层try语句中的else子句就会引发一个它自己的TypeError异常。这就会按照原来的样子生成类似于字符串的对象(在except子句的外面),了解了吗?
但你可能会问,如果给构造函数添加几个参数,结果将如何呢?...如果__len__返回零(且没有实现覆盖这种行为的__nonzero__),对象在布尔上下文中将被视为假(就像空的列表、元组、字符串和字典一样)。...__setitem__(self, key, value):这个方法应以与键相关联的方式存储值,以便以后能够使用__getitem__来获取。当然,仅当对象可变时才需要实现这个方法。...(key, int): raise TypeError if key < 0: raise IndexError class ArithmeticSequence...""" check_key(key) self.changed[key] = value # 存储修改后的值 这些代码实现的是一个算数序列
构造方法用来初始化新创建对象的状态,大多数子类不仅要拥有自己的初始化代码,还要拥有超类的初始化代码。...原因是这样的:在SongBird中,构造方法被重写,但新的构造方法没有任何关于初始化hungry特性的代码。...对于序列来说,这就是元素的个数。对于映射来说,则是键-值对的数量。 __getitem__(self,key):这个方法返回与所给键对应的值。...__setitem__(self,key,value):这个方法应该按一定的方式存储和key相关的value,该值随后可使用__getitem__来获取。当然,只能为可以修改的对象定义这个方法。...if not isinstance(key,(int,long)):raise TypeError ...
需要开启更大的内存区域,将原始的属性赋值过去 问题:如果开启的容量太大(为了效率牺牲了空间),将造成内存的浪费 解决方案:在创建对象是告诉系统这个对象只有哪些属性,也就是固定了对象的属性数量,这样就可任意要多少开多少...语法的原理 __getattribute__ 该函数也是用来获取属性 在获取属性时如果存在__getattribute__则先执行该函数,如果没有拿到属性则继续调用__getattr__函数,如果拿到了则直接返回...__dict__['halo'] = 'hi' # 直接通过操作 __dict__ 也可以完成属性的增改 print(b.halo) # hi []的实现原理(__getitem__ __setitem...__ __delitem__) 任何的符号,都会被解释器解释称特殊含义,例如 . [] () __getitem__ 当你用中括号去获取属性时 执行 __setitem__ 当你用中括号去设置属性时...,我们可以自定义运算符来实现,让自定义对象也支持比较符 上述代码中.other指的是另一个参与比较的对象 大于和小于只要实现一个即可,符号如果不同解释器会自动交换两个对象的位置 迭代器协议 迭代器:是指具有
,执行结果一样,不过这样有些多此一举,没有任何意义 执行结果: XiaoBai is eating abc 其实静态方法的作用就是让函数与类解除关系,不让其继承和访问类的内容。...) #cool , 那现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?...,@property下def flight_status的细节对于客户来说是都看不到的 输出, 说不能更改这个属性,我擦。。。。...Foo'> #f这个对象来自Foo这个类 #Foo这个对象来自type这个类 上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo...所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
索引对象Index Series和DataFrame中的索引都是Index对象 示例代码: print(type(ser_obj.index)) print(type(df_obj2.index))...'> Int64Index([0, 1, 2, 3], dtype='int64') 索引对象不可变,保证了数据的安全 示例代码: # 索引对象不可变 df_obj2.index[0] = 2 运行结果...("Index does not support mutable operations") 1405 1406 def __getitem__(self, key): TypeError...: Index does not support mutable operations 常见的Index种类 Index,索引 Int64Index,整数索引 MultiIndex,层级索引 DatetimeIndex...’: ’label3’] 注意,按索引名切片操作时,是包含终止索引的。
比如Python的序列协议只需要__len__和__getitem__两个方法,Python的迭代协议只需要__getitem__一个方法,它们不是正式的接口,只是Python程序员默认的约定。...TypeError: Vector indices must be integers 第3版:动态存取属性 通过实现__getattr__和__setattr__,我们可以对Vector类动态存取属性。...代码如下: shortcut_names = 'xyzt' # 4个分量属性名 def __getattr__(self, name): cls = type(self) # 获取实例所属的类...__setattr__(name, value) # 其他name可以赋值 值得说明的是,__getattr__的机制是:对my_obj.x表达式,Python会检查my_obj实例有没有名为x的属性...我也不知道,略过就好。
要判断一个对象是否是可迭代对象(iterable),我们可以使用Python的内置函数和特性来完成。...,存在一些局限性和潜在的漏洞:不是所有可迭代对象都继承自Iterable: Python中的迭代器协议定义了一个对象是可迭代的,如果它有一个__iter__()方法或者一个__getitem__()方法...例如,一些自定义的迭代器类可能直接实现了__iter__()或__getitem__()方法,而没有显式地继承Iterable。...如果对象是可迭代的,`iter` 函数将返回一个迭代器;否则,会引发 `TypeError` 异常。...`__iter__` 或 `__getitem__` 方法 可迭代对象通常实现了 `__iter__` 方法(返回一个迭代器),或者实现了 `__getitem__` 方法(支持通过索引访问元素)。
dict类型可以说是python里模块的命名空间,实例的属性,函数的关键字参数都有其的参与。...set的实现也依赖于散列表 常见的字典方法: 如之前所述: Container: __contains__ Iterable: __iter__ Sized: __len__ Mapping: __getitem...(str) d[2] Out[21]: '' 在这里的输入值必须是可调用对象,比如str,list,set,int,string是不行的。...标准库中字典的变种: collections里的 OrderedDict:在添加键的时候会保持顺序,popitem是默认删除最 ChainMap:可容纳数个不同的映射对象,在进行键查找时会被作为一个整体查找...集合:本质是许多唯一对象的聚集 交集&,并集|这些基本集合操作都有
同时,当判断一个list的布尔值时,如果list没有实现__bool__方法,也会尝试调用__len__方法 实现了__reversed__方法,意味着可以实现反转操作 实现了__getitem__方法...确实如此,但是当我们查看列表list、字符序列str、元组tuple的继承链时,发现在其mro列表中并没有Sequence和MutableSequence类,也就是说,这些内置类型并没有直接继承自这两个抽象基类...,那么为什么我们在文章的开头还要说他们都是序列类型呢?...甚至都不必这么严格,可能只需要实现__len__,__getitem__两个方法就可以称作是不可变序列类型。对于可变序列也同样如此。 鸭子类型的思想贯穿了Python面向对象编程的始终。...是一个宏扩展包含了更多扩展属性用于管理数组,比如引用计数以及数组大小等内容。
,只是还没有实现相应的功能。...__(self, item): if not isinstance(item, int): raise TypeError if 0 getitem__(item):根据索引查询某个索引的数据,给定一个索引值,直接返回顺序表中该位置的数据即可,如果给的索引值超出了索引范围,应该直接抛出 IndexError 。...def remove(self, i): if not isinstance(i, int): raise TypeError if i 没有实现动态扩容的方法,不像 Python 中的列表有自动扩容的机制,如果需要的话可以继续实现扩容的方法。
Python(六) 發佈於 2019-04-12 本篇,我们说说 Python 中的面向对象高级编程的基本概念。 数据封装、继承和多态只是面向对象程序设计中最基础的 3 个概念。...__slots__ 正常情况下,当我们定义了一个 class,创建了一个 class 的实例后,我们可以给该实例绑定任何属性和方法: # 给实例绑定一个属性 p = Person() p.name =..._getitem__(self, n): if isinstance(n, int): # n是索引 a, b = 1, 1 for x...注意,只有在没有找到属性的情况下,才调用 __getattr__,已有的属性,比如 name,不会在 __getattr__ 中查找。...__members__.items(): print(name, '=>', member, ',', member.value) # value 属性则是自动赋给成员的 int 常量,
", line 17, in d.eat() TypeError: eat() missing 1 required positional argument: 'self' 想让上面的代码可以正常工作有两种办法...调用时主动传递实例本身给eat方法,即d.eat(d) 2..../属性方法.py", line 16, in d.eat() TypeError: 'NoneType' object is not callable 正常调用如下 d = Dog...试试吧 f = Flight("CA980") f.flight_status f.flight_status = 2 输出, 说不能更改这个属性,我擦。。。。,怎么办怎么办。。。...注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() class Foo: def
领取专属 10元无门槛券
手把手带您无忧上云