Python有趣而有用

我从事python编程已经有好几年了,但是最近我意识到很多有用的技巧和有趣的时刻过去了,也许我不是唯一的一个,所以我决定在这里列出它们,希望这些技巧对工作中的人有用或者使我彼此认识与这种语言更接近。

与python中的许多语言一样,1等于True,0等于False,即

1 == True. 

看来,这怎么了? 但是,这具有一些副作用,因为相同的对象必须具有相同的哈希,因此您将无法将键1和True塞入一个字典中。

  >>> a = {1: "one", 0: "zero", True: "true", False: "false"} # -> {1: 'true', 0: 'false'} 

它还允许以下操作:

  >>> print(2 * False + True) # -> 1 

在此示例中,字符串被用作字典值,​​但是,我经常想将它们用作字典键,我总是很烦恼,当使用花括号创建字典时,您需要在引号中指定字符串,我想省略它们,如果创建字典通过dict()构造函数。

  >>> {"one": 1, "two": 2, "three": 3} == dict(one=1, two=2, three=3) # -> True 

另外,不仅使用字典,而且使用花括号创建集合(集合)。

  >>> a = {1, 2, 3} 

为了合并这两个集合,出于某种原因,我想使用+运算符,这可能是由于字符串的连接方式所致。 但是,python不支持该运算符用于集合。 但是,当然,这并不意味着我们总是必须使用函数,创建者更系统地解决了这个问题,并增加了对语言集(不仅仅是并集)上的基本操作的支持,并将其“挂”在逻辑运算符上

 a = {1, 2, 3} b = {0, 2, 4} print(a & b) # -> {2} print(a | b) # -> {0, 1, 2, 3, 4} print(a ^ b) # -> {0, 1, 3, 4} print(a - b) # -> {1, 3},    #     

从3.7版开始,继续关于字典的讨论,语言规范确保字典保留元素的插入顺序,不再需要OrderedDict。

www.python.org/downloads/release/python-370
mail.python.org/pipermail/python-dev/2017-December/151283.html

 d = dict(zero='Cero', one='Uno', two='Dos', three='Tres', four='Cuatro', five='Cinco', six='Seis', seven='Siete', eight='Ocho', night='Nueve') for index, (key, value) in enumerate(d.items()): print(f"{index} is {key} in England and {value} in Spain") 

注意输出行,它以前缀f开头-这是python 3.6中引入的一种特殊类型的行。

该语言有三种类型的字符串:常规字符串(用不带引号的引号表示),原始\未处理(原始),其中特殊字符(如\ n)不作为文本和f线本身进行处理和插入。

创建它们是为了简化输出,python支持大量的输出方法:

 print("result" + str(2)) #   , python   #      #  ,     print("result", 2) # print      , #        , #        , #      print("result %d" % 2) # %-,      C. print("result %d %.2f" % (2, 2)) # https://docs.python.org/3.4/library/string.html#formatspec print("result %(name)s" % {"name": 2}) #      print("{}".format(2)) #      format() #       print("{0} {1} {0}".format(1, 2)) #          #     #     #        ,    print("{} {}".format(2)) # -> IndexError: tuple index out of range print("{0} {0}".format(2, 3)) # -> 2 2       #     from math import pi #         print("{:.2f}".format(pi)) # -> 3.14 from string import Template #      s = Template("result $res") #       print(s.substitute(res = [3, 4])) 

现在添加了更多和f线。 范围中的任何变量都可用,您可以调用函数,通过键获取元素,此外,它们还支持格式字符串。

 from math import pi result = 4 name = "user" print(f"{name:84s} pi= {pi:.2f}, result={result}, {name[2]}") # -> user pi= 3.14, result=4, e from datetime import datetime print(f"{datetime.now():%Y:%m-%d}") 

它们所有其他输出方法都快 ,因此,如果您可以使用python3.6,则建议您使用它们。

最酷的python之一-不是对象和基元在其中打包和解包,而是参数和集合。

 def func(*argv, **kwargs) 

但是,实现中存在一个体系结构缺陷:

  • argv-一个元组,其值不能更改,值不能添加或删除
  • kwargs是可变的字典,因此无法进行缓存

缺点当然并不大,但是仍然不能使您无法直接将kwargs传输到基于字典的缓存,另一方面,如果您将列表添加到元组,那么也不能将这样的元组添加到字典中。

集合也是基于哈希表创建的,这意味着必须对值进行哈希处理,此外,集合本身是可变且非哈希的类型,还有一种特殊类型的Frozenset-不可变的集合(不要问我为什么需要它)。

他们讨论了Frozendict类型的创建,但尚未添加(尽管它已经至少有一个应用程序-kwargs)。 对于一本不变的字典,必须抽出 namedtuple。 以及笔记和朴实的课程。

在他的学生\学年中,谁决定写一个循环来显示数组的值,并最终对逗号感到愤怒,每次他决定得分或重写为漂亮时,仅在2-3门课程中他才了解联接方法? 还是我是唯一的一个?

字符串的join方法的令人不快的功能之一是它仅适用于字符串元素,如果集合中至少有一个非字符串,则必须使用生成器表达式,这似乎对这种简单任务来说太复杂了,但是,有一种方法可以简化列表值的输出(不带括号) 。

 a = list(range(5)) print(" ".join(a)) # -> TypeError: sequence item 0: expected str instance, int found print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4 print(*a) # -> 0 1 2 3 4 

由于字符串也是集合,因此它们也可以“联接”。

 print('-'.join("hello")) # -> hello 

考虑上一个示例中的这一行。

 print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4 

生成器表达式不带任何括号就传递给join函数;可以省略括号以简化代码读取。 Python负责表达。

 print(sum(i**2 for i in range(10))) # -> 285 

另外,创建元组时可以省略括号:

 article = "python", 2018, "LinearLeopard" #   theme, year, author = "python", 2018, "LinearLeopard"#   theme, year, _ = "python", 2018, "LinearLeopard" #     #    # ,  , #  -   , #    #  theme, _, _ = "python", 2018, "LinearLeopard" #    theme, *, author = "python", 2018, "LinearLeopard" #    # ,   #  , # ,  #   #   

星号也可以在函数声明中使用,因此您可以创建只能由key指定的参数。

 def sortwords(*wordlist, case_sensitive=False): 

您可以根据需要传递任意多个参数,而不必担心其中之一会被视为case_sensitive参数的值。

这是可能的。

 def func(first, second, *, kwonly): 


我们将仔细研究*与*参数的区别。

 def func(first, second, *, kwonly=True): print(first, second, kwonly) def func2(first, second, *args, kwonly=True): print(first, second, *args, kwonly) func(1) #-> TypeError: func() missing 1 required positional argument: 'second' func(1, 2) #-> 1 2 True func(1, 2, False) #-> TypeError: func() takes 2 positional arguments but 3 were given #  *    ,  #        #   func(1, 2, kwonly=False) #-> 1 2 False func2(1, 2, False) #-> 1 2 False True # *args      # ,       #    (>2)  #  


一个有趣的功能与默认参数相关:默认参数是在模块编译成字节码的阶段计算出来的,因此最好不要在其中使用可变类型。 我们声明一个将元素添加到列表末尾的函数,如果省略第二个参数,则该函数返回仅包含该元素的新列表。

 def add_to(elem, collection=[]): collection.append(elem) return collection a = ["a", "c"] print(add_to("b", a)) # -> ['a', 'c', 'b'] print(add_to("a")) # -> ['a'] print(add_to("b")) # -> ['a', 'b']   'a'? 

默认值存储在__defaults__字段中,您可以随时查找其中的内容。

 print(add_to.__defaults__) # -> (['a', 'b'],) 

由于默认参数(一个空列表)是在程序启动时创建的,并且没有每次都重新创建,因此我们完全可以得到这种行为。

如果将默认值设为不可变类型,并在函数主体中创建列表,则可以解决此问题:

 def add_to(elem, collection=None): collection = collection or [] collection.append(elem) return collection 

注意命令

 collection = collection or [] 

这是一个较短的(虽然不太清楚,但不是所有人)类似物

 collection = collection if collection else [] 


链接到下一部分

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


All Articles