The problem of organizing user input is extremely common in the programming process. Often, it's enough to convert characters to lowercase or uppercase, and sometimes you can use the regular expression module "Regex" to do the job. But if the problem is complex, there may be a better way to solve it:
user_input = "Thisnstring hastsome whitespaces...rn" character_map = { ord('n') : ' ', ord('t') : ' ', ord('r') : None } user_input.translate(character_map)# This string has some whitespaces...
In this example, you can see that the space characters "n" and "t" have been replaced with a single space, "r ” were deleted. This is just a very simple example. We can go further and use the "unicodedata" package to generate a large remapping table, and use "combining()" in it to generate and map. We can
If you slice the iterator, a "TypeError" will be returned, indicating that the generator object has no subscript, but we can use a simple solution to solve this problem:
import itertools s = itertools.islice(range(50), 10, 20)# <itertools.islice object at 0x7f70fab88138> for val in s: ...
We can use "itertools.islice" to create an "islice" object, which is an iterator that can produce the items we want. However, it should be noted that this operation uses all generator items before the slice, as well as all items in the "islice" object.
Sometimes you have to deal with files that start with unwanted lines (such as comments). "itertools" once again provides a simple solution:
string_from_file = """ // Author: ... // License: ... // // Date: ... Actual content... """ import itertools for line in itertools.dropwhile(lambda line: line.startswith("//"), string_from_file.split("n")): print(line)
This code only prints the content after the initial comment part. This method is useful if we only want to discard the beginning of the iterable object (in this case, the beginning comment line), but we don't know how long we want this part to be.
When we use the following function, it will be useful to create a function that only requires keyword arguments as input to provide a clearer function definition. Helpful:
def test(*, a, b): pass test("value for a", "value for b")# TypeError: test() takes 0 positional arguments... test(a="value", b="value 2")# Works...
As you can see, adding a "*" before the keyword argument solves the problem. If we put some parameters before the "*" parameter, they are obviously positional parameters.
For example, we all know how to use the "with" statement to open a file or acquire a lock, but can we implement our own context expressions? Yes, we can use "__enter__" and "__exit__" to implement the context management protocol:
class Connection: def __init__(self): ... def __enter__(self): # Initialize connection... def __exit__(self, type, value, traceback): # Close connection... with Connection() as c: # __enter__() executes ... # conn.__exit__() executes
This is the most common way to implement context management in Python, but there are simpler ways:
from contextlib import contextmanager @contextmanager def tag(name): print(f"<{name}>") yield print(f"</{name}>") with tag("h1"): print("This is Title.")
The above code uses the manager decorator of contextmanager to implement the content management protocol. The first part of the tag function (the part before yield) has been executed when the with block is entered, then the with block is executed, and finally the rest of the tag function is executed.
If you have ever written a program that creates a large number of instances of a certain class, then you may have noticed that your program suddenly requires a lot of memory. That's because Python uses dictionaries to represent attributes of class instances, which makes it fast, but not very memory efficient. Normally, this is not a serious problem. However, if your program is seriously affected by this, you might as well try "__slots__":
class Person: __slots__ = ["first_name", "last_name", "phone"] def __init__(self, first_name, last_name, phone): self.first_name = first_name self.last_name = last_name self.phone = phone
When we define the "__slots__" attribute, Python does not use a dictionary to represent the attribute, but uses a small fixed sized array, which greatly reduces the memory required per instance. Using "__slots__" also has some disadvantages: we cannot declare any new attributes, we can only use existing attributes on "__slots__". Moreover, classes with "__slots__" cannot use multiple inheritance.
If you don't want to optimize the program's usage of memory or CPU, but want to directly limit it to a certain number, Python also has a The corresponding library can do this:
import signal import resource import os # To Limit CPU time def time_exceeded(signo, frame): print("CPU exceeded...") raise SystemExit(1) def set_max_runtime(seconds): # Install the signal handler and set a resource limit soft, hard = resource.getrlimit(resource.RLIMIT_CPU) resource.setrlimit(resource.RLIMIT_CPU, (seconds, hard)) signal.signal(signal.SIGXCPU, time_exceeded) # To limit memory usage def set_max_memory(size): soft, hard = resource.getrlimit(resource.RLIMIT_AS) resource.setrlimit(resource.RLIMIT_AS, (size, hard))
We can see that the above code snippet also contains options to set the maximum CPU running time and maximum memory usage limit. When limiting the runtime of a CPU, we first obtain the soft and hard limits for that specific resource (RLIMIT_CPU) and then set them using the number of seconds specified via parameters and the previously retrieved hard limit. Finally, if the CPU exceeds the limit, we signal the system to exit. In terms of memory usage, we retrieve the soft and hard limits again and set it using "setrlimit" with the "size" parameter and the previously retrieved hard limit.
Some languages have a very obvious mechanism to export members (variables, methods, interfaces). For example, in Golang only members starting with capital letters are exported . However, in Python, all members are exported (unless we use "__all__"):
def foo(): pass def bar(): pass __all__ = ["bar"]
In the above code, we know that only the "bar" function is exported. Likewise, we can leave "__all__" empty so that nothing will be exported, which will cause an "AttributeError" when imported from this module.
为一个类实现所有的比较运算符(如 __lt__ , __le__ , __gt__ , __ge__)是很繁琐的。有更简单的方法可以做到这一点吗?这种时候,「functools.total_ordering」就是一个很好的帮手:
from functools import total_ordering @total_ordering class Number: def __init__(self, value): self.value = value def __lt__(self, other): return self.value < other.value def __eq__(self, other): return self.value == other.value print(Number(20) > Number(3)) print(Number(1) < Number(5)) print(Number(15) >= Number(15)) print(Number(10) <= Number(2))
这里的工作原理究竟是怎样的呢?我们用「total_ordering」装饰器简化实现对类实例排序的过程。我们只需要定义「__lt__」和「__eq__」就可以了,它们是实现其余操作所需要的最小的操作集合(这里也体现了装饰器的作用——为我们填补空白)。
并非本文中所有提到的功能在日常的 Python 编程中都是必需或有用的,但是其中某些功能可能会不时派上用场,而且它们也可能简化一些原本就很冗长且令人烦恼的任务。还需指出的是,所有这些功能都是 Python 标准库的一部分。而在我看来,其中一些功能似乎并不像标准库中包含的标准内容,所以当你使用 Python 实现本文提到的某些功能时,请先参阅 Python 的标准库,如果你不能找到想要的功能,可能只是因为你还没有尽力查找(如果真的没有,那它肯定也存在于一些第三方库)。
The above is the detailed content of Advanced Python programming, eight commonly used skills!. For more information, please follow other related articles on the PHP Chinese website!