python的有趣性和实用性。 第二部分

上一篇文章中,我们研究了python语言的几个有趣之处,当然,它们并不限于一篇文章,因此我们将继续。

一条评论检查了以下代码:

SEX = 'Female', 'Male' sex = SEX[True] # -> Male sex = SEX[False] # -> Female 

之所以起作用,是因为逻辑数据类型等于0和1, 开始时没有特殊类型,而使用了值0和1,并且当输入时,我们决定从整体继承。

 print(int.__subclasses__()) # -> [<class 'bool'>] 

但是回到获取列表值,假设我们有以下数据:

 books = [["Sherlock Holmes", "Arthur Conan Doyle", 1986, True, 12.51], ["The Lost World", "Arthur Conan Doyle", 2015, False, 5.95], ["The Art of Computer Programming", "Donald E. Knuth ", 2017, True, 190.54] ] 

当然,通过硬编码索引引用值不是我们的方法。 您可以创建一个常量,例如AUTHOR并指定它,但是可以更进一步:

 TITLE_AUTHOR = slice(0, 2) PRICE_IN_STOCK = slice(3, 5) print(books[0][TITLE_AUTHOR]) print([book for book in books if book[PRICE_IN_STOCK] > [True, 10.0]]) 

我们可以创建一个切片对象,并向其指示感兴趣的字段位于什么索引处。 我们甚至还可以勇敢地编写类似于该块最后一行的内容,该行显示仓库中可用的书籍,且价格超过10本书。 该代码将起作用,因为列表和元组的比较是按字典顺序进行的:首先比较第一个元素,然后比较第二个,依此类推,即in_stock“ field”为false的任何对象都将小于列表[True,10.0],因为正确>错误。

注意:当然,此代码不应在项目中使用,但是最好限制自己仅获取切片的一些值,最好在数据库中进行选择,无论是在Pandas中还是作为Book类的方法。 您可以使用namedtuple并编写一个小模块,在其中放置具有相似选择的方法。

我们已经考虑了只能通过键传递给函数的参数。 最近,在研究布尔函数文档时 ,我发现了一个下标:
在版本3.7中更改:x现在是仅位置参数。
现在, PEP 570正在开发中,这将打开设置此类参数的可能性,这在参数名称无关紧要时非常有用,例如bool(),pow()等。

语法草案如下所示:

 def name(positional_only_parameters, /, positional_or_keyword_parameters, *, keyword_only_parameters): 

返回bool函数,其功能类似于执行代码时检查条件和循环

 if obj: #  while obj: 

python执行了一个非常有趣的过程来输出布尔值:

  1. 如果对象实现__bool __()方法,则返回调用此方法的结果
  2. 否则,检查是否实现了__len __()方法,如果已实现,则检查其是否返回,如果为0,则结果为False。
  3. 如果两种方法均未实现,则返回True。

 class A: pass a = A() print(bool(a)) # -> True 

整数实现__bool__方法,标准集合不实现它,但是实现__len__方法:

 print(dir(int)) # -> ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', ... print(dir(list)) # -> ['__add__', '__class__', '__contains__', ... 

另一条评论中 ,给出了类属性的“非标准”行为:

 class Example: arr=[] def __init__(self): pass a = Example() b = Example() a.arr.append(1) print(a.arr) # -> [1] print(b.arr) # -> [1] print(Example.arr) # -> [1] 

分类和对象的属性非常重要;从对象突然创建对象的属性。
重要的是要了解类主体中声明的任何字段和方法都属于该类。 要为对象创建属性,您需要通过self或在程序文本中通过object变量在类方法中将其分配给该对象。

如果您感到困惑,让我们解析前面的代码,在其中创建该类的两个实例,然后通过其中一个对象将1添加到arr字段中。 但是对象中没有此类属性,构造函数为空,因此python在类中查找并找到了该属性,但是该类的所有实例都共享该属性。 您可以在最后一行验证这是该类的属性,因为通过该属性的名称访问该类不会产生任何错误。

在学习新语言时,重要的是要了解每种语言都有其自己的理念,并且并非所有语言都应具有static关键字。 有时其他机制也提供类似的机制。

最清楚的是,python不是java的想法说明了通过常规分配在对象和类中添加了字段:

 def make_title(self): if self.title == 'Mister': return 'Mr. ' + self.surname class Person: pass john = Person() john.title = 'Mister' john.name = 'John' john.surname = 'Peterson' john.age = 33 Person.make_title = make_title print(john.make_title()) 

一般建议:不要将可变类型存储为类的实例,这很麻烦,但是,如果您知道自己在做什么,那么就可以充分利用此功能,主要的事情是在开始时仔细考虑所有内容并在以后进行文档记录。

例如,创建一个存储指向其所有实例的链接的类非常简单:

 class RememberAll(): instances = [] def __init__(self): self.instances.append(self) a = RememberAll() b = RememberAll() print(RememberAll.instances) #-> [<__main__.RememberAll object at 0x7faa4a5ab7b8>, <__main__.RememberAll object at 0x7faa4a523c88>] 

您可以实现某些物理对象的类,并在更改其特性时调用用于重新计算系统其他元素的特性的方法。 或记住窗体上的所有滑块,并在移动一个时自动移动其余的滑块。 我不敢说这种实现总是简单明了的,但是有时它可能是有用的。

好吧,既然我们接触了物理学,我想提到@运算符。 是的,有一个 。 它是为矩阵乘法而引入的,这是最有趣的,但是它似乎尚未针对任何标准数据类型实现,也就是说,它最初仅是针对第三方库引入的。 但是没有什么可以阻止您通过实现__matmul__,__rmatmul__,__imatmul__方法来增加对数据类型的支持

 class Person: def __init__(self, name): self.name = name def __matmul__(self, msg): return "@" + self.name + " " + msg john = Person("John") print(john @ "hello") # -> @John hello 

Source: https://habr.com/ru/post/zh-CN422311/


All Articles