哈尔滨网站建设方案策划怎么生成网站地图
web/
2025/9/25 23:36:23/
文章来源:
哈尔滨网站建设方案策划,怎么生成网站地图,建立企业网站的好处,wordpress打开页面很慢《流畅的Python》笔记。本篇是Python进阶篇的开始。本篇主要是对Python特殊方法的概述。1. 前言 数据模型其实是对Python框架的描述#xff0c;它规范了这门语言自身构件模块的接口#xff0c;这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。不管在哪种框架下写… 《流畅的Python》笔记。本篇是Python进阶篇的开始。本篇主要是对Python特殊方法的概述。 1. 前言 数据模型其实是对Python框架的描述它规范了这门语言自身构件模块的接口这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。不管在哪种框架下写程序都会花费大量时间去实现那些会被框架本身调用的方法Python也不例外。Python解释器碰到特殊句法时会使用特殊方法去激活一些基本的对象操作这些特殊方法的名字以两个下划线开头以两个下划线结尾所以特殊方法也叫双下方法 dunder method这些特殊方法名能让自己编写的对象实现和支持以下的语言构架并与之交互 迭代、集合类、属性访问、运算符重载、函数和方法的调用、对象的创建和销毁、字符串表示形式和格式化、管理上下文即with块。 下面通过一些例子来介绍常用的特殊方法。 2. Python风格纸牌 首先介绍两个特殊方法__getitem__和__len__这两个特殊方法。以下代码创建了一个纸牌类 import collectionsCard collections.namedtuple(Card, [rank, suit])class FrenchDeck:ranks [str(n) for n in range(2, 11)] list(JQKA)# 黑桃红桃方块梅花suits spades diamonds clubs hearts.split()def __init__(self):# 嵌套循环self._cards [Card(rank, suit) for suit in self.suits for rank in self.ranks]def __len__(self):return len(self._cards)def __getitem__(self, position):return self._cards[position] namedtuple即命名元组类似于C/C中的struct定义如下 collections.namedtuple(typename, field_names, verboseFalse, renameFalse) 第一个参数是元组名第二个是该元组中含的属性名第三个参数表示在构建该命名元组之前先打印出该命名元组的结构如果在控制台输入第3行代码并置verbose为True的话会输出该命名元组的内部结构实际上它是一个继承自tuple的类由于输出过长请大家自行实验如果该命名元组的元素名中有Python关键字则需要置第四个参数为True这些与关键字重名的元素名会被特殊处理。 用命名元组创建一个不带方法的对象十分简单 from chapter20 import Card, FrenchDeckbeer_card Card(7, diamonds)beer_card
Card(rank7, suitdiamonds) 由于FrenchDeck实现了__getitem__方法所以可以像操作List或Tuple一样操作FrenchDeck比如随机访问切片 deck FrenchDeck()len(deck)
52deck[0]
Card(rank2, suitspades)deck[-1]
Card(rankA, suithearts)from random import choicechoice(deck)
Card(rank4, suitclubs)choice(deck)
Card(rankJ, suitclubs)deck[:3]
[Card(rank2, suitspades), Card(rank3, suitspades), Card(rank4, suitspades)]deck[12::13]
[Card(rankA, suitspades), Card(rankA, suitdiamonds),
Card(rankA, suitclubs), Card(rankA, suithearts)] 由于实现了该方法FrenchDeck还是个可迭代对象即可以用for循环对其访问也可以反向访问reversed: for card in deck:... print(card)Card(rank2, suitspades)
Card(rank3, suitspades)
Card(rank4, suitspades)
-- snip --
Card(rankQ, suithearts)
Card(rankK, suithearts)
Card(rankA, suithearts) 迭代通常是隐式的譬如说一个集合类型没有实现__contains__方法那么in运算符就会按顺序做一次迭代搜索调用__getitem__于是in运算符可以用在FrenchDeck上 Card(2, spades) in deck
True 如果对上述deck变量调用sorted函数Python将按ASCII码进行排序但这并不是扑克牌的正确排序所以下面我们自定义排序方法 suit_values dict(spades3, hearts2, diamonds1, clubs0)def spades_high(card):rank_value FrenchDeck.ranks.index(card.rank)return rank_value * len(suit_values) suit_values[card.suit]for card in sorted(deck, keyspades_high):print(card) 此时输出的结果就是先按点数排序再按花色排序。 3. 如何使用特殊方法 需要明确一点特殊方法的存在是为了给Python解释器调用到作为程序员并不需要调用他们也即是说没有my_object.__len__()这种写法而应该是len(my_object)。说到__len__方法如果是Python内置类型CPython会抄个近路该方法实际上会直接返回PyVarObject里的ob_size属性而PyVarObject是表示内存中长度可变的内痔对象的C语言结构体。 很多时候特殊方法的调用是隐式的比如for i in x:这个语句背后其实用的是iter(x)而这个函数的背后则是x.__iter__()方法当然前提是这个方法在x中被实现如果没被实现则会调用__getitem__方法。 直接调用这个值比调用一个方法快很多。直接调用特殊方法的频率应该远远低于你去实现它们的次数。 通过内置的函数例如leniterstr等来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法通常还提供额外的好处而且对于内置的类来说它们的速度更快。 还有一点值得注意不要想当然地随意添加特殊方法比如__foo__之类的因为虽然现在这个名字没有被Python内部使用以后就不一定了。 3.1 自定义向量Vector 使用5个特殊方法实现Vector的字符串输出取绝对值如果是复数则是取模返回布尔值加法和数乘等运算 from math import hypotclass Vector:def __init__(self, x0, y0):self.x xself.y ydef __repr__(self):return Vector(%r, %r) % (self.x, self.y)def __abs__(self):return hypot(self.x, self.y)# 在Python中只有0NULL才是False其余均为Truedef __bool__(self):# 更简单的写法是# return bool(self.x or self.y)return bool(abs(self))# 实现加法运算符重载def __add__(self, other):return Vector(self.x other.x, self.y other.y)# 实现乘法运算符重载这里是数乘且还没有实现交换律需要实现__rmul__方法def __mul__(self, scalar):return Vector(self.x * scalar, self.y * scalar) Python有一个内置函数叫做repr。该函数通过特殊方法__repr__来得到一个对象的字符串表示形式如果没有该特殊方法当我们在控制台打印一个向量对象时得到的字符串可能是Vector object at 0x10e00070 # 代码
v1 Vector(2, 4)
v2 Vector(2, 1)
print(v1 v2)
print(abs(v1))
print(v1 * 3)# 结果
Vector(4, 5)
4.47213595499958
Vector(6, 12) __repr__与__str__的区别与联系前者方便我们调试和记录日志后者则是给终端用户看的。后者是在str()函数被使用或者是在print函数打印一个对象的时候才被调用它返回的字符串对终端用户友好。如果只想实现这两个特殊方法中的一个__repr__是更好的选择因为如果一个对象没有__str__函数Python又需要调用它时解释器会用__repr__代替。 上述Vector类实现了__bool__方法它可用于需要布尔值的上下文中if, while, and, or, not等。默认情况下我们自己定义的类的实例总被认为是True除非重写了这个类的__bool__或__len__方法。bool(x)的背后是调用x.__bool__()如果不存在__bool__方法那么bool(x)会尝试调用x.__len__()如果该方法返回0则bool返回False否则返回True。 3.2 为什么len不是普通方法 “实用胜于纯粹”Python之禅里的一句话。len之所以不是一个普通方法是为了让Python自带的数据结构可以走后门abs也是同理。但多亏了它是特殊方法我们也可以把len用于自定义数据类型。这种处理方式在保持内置类型的效率和保证语言的一致性之间找到了一个平衡点也印证了“Python之禅”中的另一句话“不能让特例特殊到考试破坏既定规则”。 4. 总结 通过实现特殊方法自定义数据类型可以表现得跟内置类型一样从而让我们写出更具Python风格Pythonic的代码。后面的内容将围绕更多的特殊方法展开。 迎大家关注我的微信公众号代码港 个人网站 www.vpointer.net ~
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81875.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!