Zusammenfassung der seltenen Python-Wissenspunkte

Zusammenfassung der seltenen Python-Wissenspunkte

Dieser Artikel leiht viel von  https://github.com/leisurelicht/wtfpython-cn

□ außer ... finally: Die gesamte Logik in finally wird ausgeführt, unabhängig davon, ob das gesamte Programm normal ausgeführt wird oder nicht. Gleichzeitig überschreibt die Rückgabe in finally das Ausführungsergebnis der vorherigen Logik, und selbst Ausnahmen werden ignoriert. Daher wird empfohlen, nur ressourcenbezogene Logik endgültig hinzuzufügen

def calculate(division):
    try:
        return 100 / division
    except ZeroDivisionError as e:
        raise ValueError("Invalid inputs")
    finally:
        return 0
    
print(calculate(0))

'''
最后不会报错,而是正常退出返回 0
'''

□ for ... in: Der for ... in-Vorgang ruft zuerst __iter__ auf, um einen Iterator abzurufen, und ruft dann __next__ auf, um der Reihe nach auf die Elemente zuzugreifen. Wenn daher der Inhalt des Elements während des Iterationsprozesses geändert wird, weil __next__ gemäß dem Adressbit auf das Element zugreift, tritt eine abnormale Situation auf.

Hier gibt es noch einen weiteren Wissenspunkt: iterable iterable enthält Iterator und iterator enthält Generator. Gleichzeitig ist es iterierbar, solange es durchlaufen werden kann, und der Iterator kann als nächstes auf Elemente zugreifen. Dies ist die einzig nützliche Methode, um Iteratoren zu durchlaufen. Lassen Sie uns kurz mit einem Bild erklären.

list_1 = [1, 2, 3, 4]
list_2 = [1, 2, 3, 4]
list_3 = [1, 2, 3, 4]
list_4 = [1, 2, 3, 4]

for idx, item in enumerate(list_1):
    del item

for idx, item in enumerate(list_2):
    list_2.remove(item)

for idx, item in enumerate(list_3[:]):
    list_3.remove(item)

for idx, item in enumerate(list_4):
    list_4.pop(idx)

Output:

>>> list_1
[1, 2, 3, 4]
>>> list_2
[2, 4]
>>> list_3
[]
>>> list_4
[2, 4]

'''
del, remove 和 pop 的不同: 

del var_name 只是从本地或全局命名空间中删除了 var_name (这就是为什么 list_1 没有受到影响). 

remove 会删除第一个匹配到的指定值, 而不是特定的索引, 如果找不到值则抛出 ValueError 异常. 

pop 则会删除指定索引处的元素并返回它, 如果指定了无效的索引则抛出 IndexError 异常.
'''
for i in range(4):
    print(i)
    i = 10 

# 在每次迭代开始之前, 迭代器(这里指 range(4)) 生成的下一个元素就被解包并赋值给目标列表的变量(这里指 i)了.
'''
output:
0
1
2
3
'''

□ python =: Die Zuweisungsoperation in Python ist nur eine einfache Referenzzuweisung für ein variables Objekt, und die beiden Referenzen verweisen tatsächlich auf dasselbe Speicherobjekt.

list1 = [1, 2, 3]
list2 = list1
list2[0] = 6

'''
list1 = [6, 2, 3]
list2 = [6, 2, 3]
'''

□ Liste ist leer: Es wird empfohlen, Liste und nicht Liste direkt zu verwenden, um zu beurteilen, ob die Liste in PEP 8 nicht leer oder leer ist.

□ Variable Objekte als Standardparameter für Funktionen verwenden: Der Standardwert des Parameters wird bereits festgelegt, wenn die Methodendefinition ausgeführt wird. Dies bedeutet, dass der Standardwert nur einmal festgelegt wird. Nachdem die Funktion definiert wurde, wird sie bei jedem Aufruf festgelegt Es gibt einen "Vorberechnungsprozess". Wenn zu diesem Zeitpunkt das variable Objekt innerhalb der Funktion geändert wird, ist die Standardeingabe danach das geänderte Objekt

#!/usr/bin/env python
# coding: utf-8

class Test(Object):
    def process_data(self, data=[]):
        # 排序
        data.sort()
        # 追加结束符
        data.append("End")
        return data

test1 = Test()
print(test1.process_data())

test2 = Test()
print(test2.process_data())

test3 = Test()
print(test3.process_data(data=["Name:123", "Age:34"]))

test4 = Test()
print(test4.process_data())

'''
输出:
['End']
['End', 'End']
["Age:34", "Name:123", 'End']
['End', 'End', 'End']
'''

Wenn Sie wirklich standardmäßig ein variables Objekt verwenden müssen, können Sie die folgende Methode verwenden

def some_func(default_arg=None):
    if default_arg is None:
        default_arg = []
    default_arg.append("some_string")
    return default_arg

 □ Nicht lokal: Nicht lokal kann nur lokale Variablen auf einer Ebene außerhalb des aktuellen Bereichs abrufen, und die Erweiterungsstufe kann nur 1 betragen

n = 0

def f():
    def inner():
        nonlocal n
        n = 2
    
    n = 1
    print(n)
    inner()
    print(n)

if __name__ == "__main__":
    f()
    print()

'''
输出:
1
2
0
'''

□ Listen-Slice: Wenn die Liste in Scheiben geschnitten wird, sollte sich der Stopp auf der logischen rechten Seite des Starts befinden, andernfalls ist die Ausgabe leer

TempStr = 'Hello World'

print(TempStr[-5:-1])
print(TempStr[-5:0])
print(TempStr[-4:-1])
print(TempStr[-5:])

'''
输出:
Worl

orl
World
'''

□ __all__: __all__ kann nur die von ... import * exportierten Objekte einschränken. Derzeit können nur die in __all__ angegebenen Objekte exportiert werden. Es können jedoch weiterhin alle Objekte explizit exportiert werden aus ... import ....

□ Abschlusswertübertragung: Der durch den Abschluss übergebene Wert wird durch die Objektadresse geleitet. Wenn also der eingehende Wert extern geändert wird, wird auch das Ergebnis innerhalb des Abschlusses beeinflusst. Wenn der eingehende Wert jedoch intern direkt geändert wird, ist der eingehende Wert des Abschlusses im lokalen Bereich ungültig und kann dazu führen, dass er nicht kopiert wird. Wenn Sie zu diesem Zeitpunkt nicht lokal verwenden, um den Wert des Abschlusses anzugeben, können Sie die externen Variablen innerhalb des Abschlusses ändern.

#!/usr/bin/env python
# coding: utf-8

def a(s):
    def b():
        print(i)
        # i = 2  # 添加该行,由于指定了局部变量,对应闭包传递过来的对象引用被覆盖,将调试在赋值前引用
        # print(i)
    i = s
    print(i)
    return b


if __name__ == '__main__':
    tb1 = a(1)
    tb1()
    tb2 = a(2)
    tb1()
    tb2()

'''
输出:
1
1
2
1
2
'''

□ Abschlusswertübertragung: Wenn beim Definieren einer Funktion innerhalb einer Schleife eine Schleifenvariable in ihrem Körper verwendet wird, wird die Schließfunktion an die Schleifenvariable gebunden, nicht an ihren Wert. Daher sind alle Funktionen Sie wird anhand des letzten der Variablen zugewiesenen Werts berechnet. 

def f():
    t = [lambda x: i*x for i in range(4)]
    return t
    
print([M(2) for M in f()])

'''
output:
[6, 6, 6, 6]
'''
'''
这个例子本质不是闭包值传递,而是正常的函数值传递
而由于每次都会创建一个局部变量,不同函数对应的局部变量的内存必然不同,因此不存在影响
'''
funcs = []
for x in range(7):
    def some_func(x=x):
        return x
    funcs.append(some_func)

Output:

>>> funcs_results = [func() for func in funcs]
>>> funcs_results
[0, 1, 2, 3, 4, 5, 6]

□ Zeitpunkt der Ausführung der in-Klausel: Im Generatorausdruck wird die in-Klausel zum Zeitpunkt der Deklaration ausgeführt, während die bedingte Klausel zur Laufzeit ausgeführt wird

array = [1, 8, 15]
g = (x for x in array if array.count(x) > 0)
array = [2, 8, 22]

print(list(g))

"""
output:
[8]
"""

array_1 = [1,2,3,4]
g1 = (x for x in array_1)
array_1 = [1,2,3,4,5]

print(list(g1))

array_2 = [1,2,3,4]
g2 = (x for x in array_2)
array_2[:] = [1,2,3,4,5]

print(list(g2))

"""
output:
[1,2,3,4]
[1,2,3,4,5]
"""

□ Multiplikation von Listenobjekten: Verwenden Sie für variable Objekte in der Liste die Multiplikation zum Kopieren, und alle kopierten variablen Objekte zeigen auf denselben Speicherplatz

# 我们先初始化一个变量row
row = [""]*3 #row i['', '', '']
# 并创建一个变量board
board = [row]*3

>>> board
[['', '', ''], ['', '', ''], ['', '', '']]
>>> board[0]
['', '', '']
>>> board[0][0]
''
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['X', '', ''], ['X', '', '']]

□ ist nicht: ist nicht ein einzelner binärer Operator, der sich von der Verwendung von is unterscheidet und nicht separat. Wenn die Variablen auf beiden Seiten des Operators auf dasselbe Objekt verweisen, ist das Ergebnis von nicht False, andernfalls ist das Ergebnis True.

□ Mit r gekennzeichnete Backslash-Zeichenfolge: Der Interpreter ändert einfach das Verhalten des Backslashs, sodass der Backslash und das nächste Zeichen direkt übergeben werden. Wenn die Zeichenfolge zu diesem Zeitpunkt mit einem Backslash endet, wird beim Scannen des Zeichenfolgenliterals ein Fehler gemeldet. SyntaxError: EOL

□ bool und int: Boolesche Werte sind Untertypen von int, daher ist der ganzzahlige Wert von True 1 und der ganzzahlige Wert von False 0

□ Klassenattribute und Instanzattribute: Intern werden Klassenvariablen und Instanzvariablen über das Wörterbuch des Klassenobjekts (dh das Attribut __dict__) behandelt. Wenn Sie es im Wörterbuch der aktuellen Klasse nicht finden können, wechseln Sie zu seiner übergeordneten Klasse. Der Operator + = ändert veränderbare Objekte an Ort und Stelle, anstatt neue zu erstellen. Daher wirkt sich das Ändern der Eigenschaften einer Instanz in diesem Fall auf andere Instanz- und Klasseneigenschaften aus.

class A:
    x = 1

class B(A):
    pass

class C(A):
    pass

Output:

>>> A.x, B.x, C.x
(1, 1, 1)
>>> B.x = 2
>>> A.x, B.x, C.x
(1, 2, 1)
>>> A.x = 3
>>> A.x, B.x, C.x
(3, 2, 3)
>>> a = A()
>>> a.x, A.x
(3, 3)
>>> a.x += 1
>>> a.x, A.x
(4, 3)


class SomeClass:
    some_var = 15
    some_list = [5]
    another_list = [5]
    def __init__(self, x):
        self.some_var = x + 1
        self.some_list = self.some_list + [x]
        self.another_list += [x]

Output:

>>> some_obj = SomeClass(420)
>>> some_obj.some_list
[5, 420]
>>> some_obj.another_list
[5, 420]
>>> another_obj = SomeClass(111)
>>> another_obj.some_list
[5, 111]
>>> another_obj.another_list
[5, 420, 111]
>>> another_obj.another_list is SomeClass.another_list
True
>>> another_obj.another_list is some_obj.another_list
True
class Base:
    inited = False
    
    @classmethod
    def set_inited(cls): # 实际可能传入Derived类
        cls.inited = True # 并没有修改Base.inited,而是给Derived添加了成员

class Derived(Base):
    pass

x = Derived()
x.set_inited()
if Base.inited:
    print("Base is inited") # 不会被执行

□ + = Operator: Der Operator + = ändert die Liste an Ort und Stelle. Die Elementzuweisungsoperation funktioniert nicht, aber wenn eine Ausnahme ausgelöst wird, wurde das Element an Ort und Stelle geändert

'''
对于不可变对象, 这里指tuple, += 并不是原子操作, 而是 extend 和 = 两个动作
这里 = 操作虽然会抛出异常, 但 extend 操作已经修改成功了
'''
some_tuple = ("A", "tuple", "with", "values")
another_tuple = ([1, 2], [3, 4], [5, 6])

>>> some_tuple[2] = "change this"
TypeError: 'tuple' object does not support item assignment
>>> another_tuple[2].append(1000) # 这里不出现错误
>>> another_tuple
([1, 2], [3, 4], [5, 6, 1000])
>>> another_tuple[2] += [99, 999]
TypeError: 'tuple' object does not support item assignment
>>> another_tuple
([1, 2], [3, 4], [5, 6, 1000, 99, 999])

□ numpy.empty (): numpy.empty () kehrt ohne Neuinitialisierung direkt zum nächsten freien Speicher zurück.

import numpy as np

def energy_send(x):
    # 初始化一个 numpy 数组
    np.array([float(x)])

def energy_receive():
    # 返回一个空的 numpy 数组
    return np.empty((), dtype=np.float).tolist()
Output:

>>> energy_send(123.456)
>>> energy_receive()
123.456

□ Wörterbuchänderung im iterativen Prozess: Versuchen Sie, das iterative Objekt während des iterativen Prozesses nicht zu ändern, da das Ergebnis häufig nicht vorhersehbar ist.

x = {0: None}

for i in x:
    del x[i]
    x[i+1] = None
    print(i)

Output (Python 3.7):
# 这个结果好像跟字典的自动扩容有关,扩容会导致散列表地址发生变化而中断循环
0
1
2
3
4

□ Generatorausdruck und Liste rekursiver Variablenbereich: Der in der Klassendefinition verschachtelte Bereich ignoriert die Namensbindung innerhalb der Klasse. Der Generatorausdruck hat einen eigenen Bereich. Ab Python 3.X haben Listenverständnisse auch einen eigenen Bereich.

# 这次我们先初始化x
x = -1
for x in range(7):
    if x == 6:
        print(x, ': for x inside loop')
print(x, ': x in global')

Output:

6 : for x inside loop
6 : x in global


x = 1
print([x for x in range(5)])
print(x, ': x in global')

Output (on Python 2.x):

[0, 1, 2, 3, 4]
(4, ': x in global')

# python 3 的列表推导式不再泄露
Output (on Python 3.x): 

[0, 1, 2, 3, 4]
1 : x in global
x = 5
class SomeClass:
    x = 17
    y = (x for i in range(10))

Output:

>>> list(SomeClass.y)[0]
5


x = 5
class SomeClass:
    x = 17
    y = [x for i in range(10)]

Output (Python 2.x):

>>> SomeClass.y[0]
17

Output (Python 3.x):

>>> SomeClass.y[0]
5

□ else: Die else-Klausel nach der Schleife wird nur ausgeführt, wenn die Schleife die break-Anweisung nicht auslöst und normal endet. Die else-Klausel nach try wird auch als "Completion-Klausel" bezeichnet, da das Erreichen der else-Klausel in der try-Anweisung bedeutet, dass der try-Block tatsächlich erfolgreich abgeschlossen wurde.

  def does_exists_num(l, to_find):
      for num in l:
          if num == to_find:
              print("Exists!")
              break
      else:
          print("Does not exist")

Output:

>>> some_list = [1, 2, 3, 4, 5]
>>> does_exists_num(some_list, 4)
Exists!
>>> does_exists_num(some_list, -1)
Does not exist


try:
    pass
except:
    print("Exception occurred!!!")
else:
    print("Try block executed successfully...")

Output:

Try block executed successfully...

□ Doppelte private Unterstreichungsvariablen: In Python  ändert (entstellt) der Interpreter die Namen __ von Klassenmitgliedern, die mit  (doppelter Unterstrich) beginnen und mit höchstens einem Unterstrich enden_NameOfTheClass

class Yo(object):
    def __init__(self):
        self.__honey = True
        self.bitch = True

Output:

>>> Yo().bitch
True
>>> Yo().__honey
AttributeError: 'Yo' object has no attribute '__honey'
>>> Yo()._Yo__honey
True

 

Ich denke du magst

Origin blog.csdn.net/a40850273/article/details/106232621
Empfohlen
Rangfolge