目录
if __name__ == "__main__
在Python中,`if __name__ == "__main__":` 这行代码是一个常见的习惯用法,它的目的是用来判断当前的Python脚本是被直接运行还是被作为模块导入到另一个脚本中。
具体来说,这里有几个关键点:
1. **`__name__` 是一个内置变量**:在Python中,每个模块都有一个内置的`__name__`变量。如果模块是被直接运行的,那么`__name__`的值就是`"__main__"`;如果模块是被导入的,那么`__name__`的值通常是模块的名称。
2. **区分直接运行和导入**:当你直接运行一个Python脚本时,你想执行脚本中的某些代码。但是,如果你把这个脚本作为一个模块导入到另一个脚本中,你可能不希望执行这些代码,
而是只希望使用模块中定义的函数、类或变量。
3. **代码封装**:把主程序逻辑放在`if __name__ == "__main__":`块中,可以让你的代码更加模块化。这意味着,这个模块既可以单独运行,也可以被其他模块导入而不会立即执行主程序逻辑。
以下是一个简单的例子来说明这一点:
```python
# example.py
def main():
print("Hello, world!")
if __name__ == "__main__":
main()
```
当你直接运行`example.py`时,输出将是:
```
Hello, world!
```
但是,如果你在另一个脚本中导入`example.py`:
```python
import example
```
这时,`example`模块会被导入,但是`Hello, world!`不会打印出来,因为`main()`函数只会在`example.py`被直接运行时调用。
这个习惯用法在Python社区中被广泛接受,并且是编写可重用代码的良好实践。
模块名————__name__
在Python中,`__name__`变量不等于`"__main__"`的情况通常发生在以下几种情境:
1. **模块被导入时**:当一个Python文件(模块)被另一个Python文件通过`import`语句导入时,`__name__`变量将被设置为该模块的名称,而不是`"__main__"`。
例如,假设有一个名为`module_a.py`的模块,它被另一个名为`script.py`的脚本导入:
```python
# module_a.py
print(__name__)
def some_function():
pass
```
```python
# script.py
import module_a
```
当你运行`script.py`时,输出将是:
```
module_a
```
在这里,`module_a`模块的`__name__`变量被设置为`"module_a"`,因为它不是作为主程序运行的,而是被`script.py`导入的。
2. **作为包的一部分被导入时**:如果一个模块是包的一部分,并且被导入,`__name__`变量将被设置为该模块的相对路径。
例如,假设有一个包结构如下:
```
mypackage/
__init__.py
submodule.py
```
在`submodule.py`中,`__name__`将被设置为`"mypackage.submodule"`。
3. **执行Python交互式解释器时**:在交互式解释器(例如,直接运行`python`或`python3`)中,`__name__`变量被设置为`"__main__"`。但是,如果你从交互式解释器中导入一个模块,那么`__name__`将不会是`"__main__"`。
4. **使用`-m`选项运行模块时**:
当你使用Python解释器的`-m`选项运行一个模块时,`__name__`会被设置为`"__main__"`。
但是,如果你导入其他模块,那些模块的`__name__`不会是`"__main__"`。
例如:
```
python -m mypackage.submodule
```
在这个例子中,`mypackage.submodule`的`__name__`将被设置为`"__main__"`,但是如果你在这个模块中导入其他模块,那些模块的`__name__`将不会是`"__main__"`。
总之,`__name__`变量不等于`"__main__"`的情况通常发生在模块被导入而不是作为主程序运行时。
装饰器
Python装饰器是一种特殊类型的函数,它可以修改或增强其他函数的功能,而无需更改原始函数的源代码。装饰器本质上是一个接收函数作为参数的函数,它返回一个新的函数或者修改过的原函数,通常用于插入日志、性能测试、权限校验、缓存、事务处理等场景。
学习【Python】一文弄懂python装饰器(附源码例子)_python 装饰器-CSDN博客
1. 计时装饰器 (@timer) 用于测量函数执行时间。
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} executed in {end_time - start_time} seconds")
return result
return wrapper
@timer
def example_function(i):
time.sleep(i)
example_function(2.5)
# 输出:example_function executed in 2.5106894969940186 seconds
timer(example_function(2))也是这个效果。
@装饰器+定义函数
装饰器(函数)
两者可以达到相同效果
只修饰离@最近的参数
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} executed in {end_time - start_time} seconds")
return result
return wrapper
@timer
def example_function2(i):
time.sleep(i)
def example_function(i):
time.sleep(i)
example_function(2.5)
# 输出:example_function executed in 2.5106894969940186 seconds
2. 日志装饰器 (@log_execution) 记录函数调用的日志。
import logging
logging.basicConfig(level=logging.INFO)
def log_execution(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned: {result}")
return result
return wrapper
@log_execution
def add(a, b):
return a + b
add(3, 5)
``输出:``INFO:root:Calling add with args: (3, 5), kwargs: {}``INFO:root:add returned: 8 1
3. 缓存装饰器 (@lru_cache) 利用functools.lru_cache实现结果缓存,避免重复计算。 from functools import lru_cache``@lru_cache(maxsize=None)``def fibonacci(n):` `if n < 2:` `return n` `else:` `return fibonacci(n-1) + fibonacci(n-2)``print(fibonacci(10))``输出:``55 1
@cache: 由于其可以处理任意对象类型,因此可能会消耗更多的内存来存储这些对象的引用。
@lru_cache: 它只缓存最近访问过的项目,所以对于需要频繁调用且结果集较大的函数来说,这是一个更节省内存的选择。
4. 类型检查装饰器 (@type_check) 确保函数参数类型正确。
def type_check(*arg_types):`
`def decorator(func):`
`def wrapper(*args, **kwargs):`
`for arg, expected_type in zip(args, arg_types):` `if not isinstance(arg, expected_type):` `raise TypeError(f"Argument {arg} is not of type {expected_type}")` `return func(*args, **kwargs)` `return wrapper` `return decorator``@type_check(int, int)``def multiply(x, y):` `return x * y``print(multiply(2, 3))``输出:``6 1
5. 单例装饰器 (@singleton) 确保类的实例唯一。 class SingletonMeta(type):` `_instances = {}` `def __call__(cls, *args, **kwargs):` `if cls not in cls._instances:` `cls._instances[cls] = super().__call__(*args, **kwargs)` `return cls._instances[cls]``class Singleton(metaclass=SingletonMeta):` `pass``s1 = Singleton()``s2 = Singleton()``print(s1 is s2)``输出:``True 1
6. 重试装饰器 (@retry_on_exception) 在异常发生时自动重试。 import random``def retry_on_exception(max_retries=3, exceptions=(Exception,), delay=1):` `def decorator(func):` `def wrapper(*args, **kwargs):` `retries = 0` `while retries < max_retries:` `try:` `return func(*args, **kwargs)` `except exceptions as e:` `print(f"Caught {e}. Retrying...")` `retries += 1` `time.sleep(delay)` `raise Exception("Max retries exceeded.")` `return wrapper` `return decorator``@retry_on_exception(max_retries=3)``def might_fail():` `if random.randint(0, 2) == 0:` `raise ValueError("Failed.")` `print("Success!")``might_fail()``输出可能为:``Caught ValueError('Failed.'). Retrying...``Caught ValueError('Failed.'). Retrying...``Caught ValueError('Failed.'). Retrying...``Max retries exceeded.``或``Success! 1
7. 性能度量装饰器 (@profile) 使用cProfile进行性能分析。 import cProfile``def profile(func):` `def wrapper(*args, **kwargs):` `profiler = cProfile.Profile()` `profiler.enable()` `result = func(*args, **kwargs)` `profiler.disable()` `profiler.print_stats()` `return result` `return wrapper``@profile``def dummy_function(n):` `sum([i**2 for i in range(n)])``dummy_function(100000)``输出为函数执行的性能统计信息。 1
8. 身份验证装饰器 (@authenticate) 确保用户已登录。 def authenticate(user_required=True):` `def decorator(func):` `def wrapper(*args, **kwargs):` `if not user_required or user_is_logged_in(): # 假设 user_is_logged_in 是验证函数` `return func(*args, **kwargs)` `else:` `raise PermissionError("User not authenticated.")` `return wrapper` `return decorator``@authenticate``def sensitive_operation():` `print("Sensitive operation performed.")``# 假设已经登录``sensitive_operation()``输出:``Sensitive operation performed. 1
9. 异步装饰器 (@asyncio.coroutine 或 async def) 用于异步操作。 import asyncio``async def async_decorator(func):` `async def wrapper(*args, **kwargs):` `print("Starting async task...")` `result = await func(*args, **kwargs)` `print("Async task finished.")` `return result` `return wrapper``@async_decorator``async def long_running_task():` `await asyncio.sleep(2)` `return "Task done."``asyncio.run(long_running_task())``输出:``Starting async task...``Async task finished. 1
10. 验证输入装饰器 (@validate_input) 确保输入满足特定条件。 def validate_input(minimum=0, maximum=100):` `def decorator(func):` `def wrapper(value):` `if not (minimum <= value <= maximum):` `raise ValueError(f"Value must be between {minimum} and {maximum}")` `return func(value)` `return wrapper` `return decorator``@validate_input(1, 10)``def process_value(value):` `print(f"Processing value: {value}")``process_value(5)``输出:``Processing value: 5
参数的优化——可以接受任何函数
*args,**kwargs,共出现两次。
def count_time(func):
def wrapper(*args,**kwargs):
t1 = time.time()
func(*args,**kwargs)
print("执行时间为:", time.time() - t1)
return wrapper
需要添加自定义参数——再套一层
import time
def count_time_args(msg=None):
def count_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
func(*args, **kwargs)
print(f"[{msg}]执行时间为:", time.time() - t1)
return wrapper
return count_time
@count_time_args(msg="baiyu")
def fun_one():
time.sleep(1)
@count_time_args(msg="zhh")
def fun_two():
time.sleep(1)
@count_time_args(msg="mylove")
def fun_three():
time.sleep(1)
if __name__ == '__main__':
fun_one()
fun_two()
fun_three()
语法糖——好甜!
在编程领域,“语法糖”(Syntactic Sugar)是一个术语,指的是编程语言提供的某种语法,它可以让代码更易于书写和理解,但实际上并不增加语言的功能。换句话说,语法糖让编程任务变得更加简洁和直观,但它背后的操作通常可以用语言中更基础的结构来实现。
以下是一些Python中常见的语法糖示例:
1. **列表推导式(List Comprehensions)**:
```python
squares = [x**2 for x in range(10)]
```
这比使用循环来创建相同列表的代码更简洁。
2. **字典推导式(Dictionary Comprehensions)**:
```python
squares_dict = {x: x**2 for x in range(10)}
```
3. **集合推导式(Set Comprehensions)**:
```python
squares_set = {x**2 for x in range(10)}
```
4. **使用`with`语句管理资源**:
```python
with open('file.txt', 'r') as file:
content = file.read()
```
这自动处理了文件的打开和关闭,无需显式调用`file.close()`。
5. **装饰器(Decorators)**:
```python
@my_decorator
def my_function():
pass
```
这是一种将功能添加到函数上的便捷方式,而不需要修改函数本身。
6. **切片(Slicing)**:
```python
my_list = [0, 1, 2, 3, 4, 5]
sublist = my_list[1:4]
```
切片允许你轻松获取列表的一部分。
7. **解包(Unpacking)**:
```python
a, b = 1, 2
```
或者
```python
first, *middle, last = [1, 2, 3, 4, 5]
```
8. **链式比较(Chained Comparison)**:
```python
if 0 < x < 10:
pass
```
9. **三元运算符(Ternary Operator)**:
```python
x = 10
value = 'even' if x % 2 == 0 else 'odd'
```
这些语法糖让Python代码更加简洁和易读,同时减少了代码量。尽管它们看起来像是语言的新特性,但实际上它们都可以用更基本的语言结构来代替。
类init self
在Python中,`__init__` 是一个特殊的方法,称为构造函数。它在创建新对象时自动调用,用来初始化对象的属性。
```python
class MyClass:
def __init__(self): # 定义构造函数
pass # 这里可以添加初始化代码
```
`self` 参数是 Python 类方法(包括构造函数)的一个约定俗成的参数,它指向实例对象本身。在定义类的方法时,你需要在参数列表中包含 `self`,并在调用这些方法时传递实例作为第一个参数。
```python
class MyClass:
def __init__(self, value): # value是形参
self.value = value # value是实参
obj = MyClass(10) # 创建实例时传入实参10
print(obj.value) # 输出10
```
在上面的示例中,`value` 是 `__init__` 方法的形式参数,而 `self.value` 是对象的属性。当我们创建 `MyClass` 的实例并传入 `10` 作为参数时,`__init__` 方法会被调用,并将 `value` 属性设置为 `10`。