Python进阶技巧二三事(十)shebang与文件格式 第一行是shebang,也称为hashbang,用于在Unix
shebang与文件格式
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 通常如果有shebang 那么shebang处于第一行 没有的话则编码类型处于第一行
第一行是shebang
,也称为hashbang
,用于在Unix系统中指定脚本解释器告诉操作系统使用哪个解释器来执行脚本文件 所以这里我们#!之后应该接的使我们的python安装路径
第二行用于指定UTF-8编码,用于正确解析代码文件中的非ASCII字符
通常如果有shebang
,那么shebang
处于第一行 没有的话则编码类型处于第一行
init.py文件
在 Python 2 中,__init__.py
文件是必须的,用于将目录标识为一个包,使得该目录中的模块可以被导入。
在 Python 3.3 及更高版本中,__init__.py
文件变得可选,Python 引入了隐式命名空间包的概念,这使得即使没有 __init__.py
文件,目录也可以被视为包。
为什么需要 __init__.py
文件
- 明确包的边界:
__init__.py
文件明确了哪些目录是包的一部分,避免了意外的命名冲突。 - 兼容性:确保代码在 Python 2 和 Python 3 中都能正常工作。
- 初始化代码:你可以在
__init__.py
文件中放置包的初始化代码,例如导入子模块、设置包级别的变量等。
假设你的项目目录结构如下:
/Users/annesheartrecord/PycharmProjects/pythonProject/effectivePyton
├── pythonmodule
│ ├── __init__.py
│ └── demo1.py
└── other_files
__init__.py
文件可以是空的,也可以包含一些初始化代码:
# __init__.py
# 这个文件可以是空的,也可以包含一些包的初始化代码
demo1.py
文件内容如下:
# demo1.py
def fibonacci(n):
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
else:
fibs = [0, 1]
for i in range(2, n):
fibs.append(fibs[-1] + fibs[-2])
return fibs
如果你没有 __init__.py
文件,Python 3.3 及更高版本仍然可以导入模块,但是在这之下的版本就会导入失败的问题,这个目录不会被认为是包,ImportError: No modulenamed my_module
定义函数修饰器
Python使用batteries included
思路来设计标准库,即在标准库中提供大量使用的模块,减少开发者对于第三方库的依赖。
Python用特殊的语法来表示修饰器decorator
,这些修饰器可以用来修饰函数。修饰器的本质是在函数执行之前以及执行完毕之后,分别运行一些附加的代码。同样在修饰器中可以访问并修改原函数的参数、返回值,以实现约束语义,调试程序,注册函数等目标。
例如我们编写一个debug修饰器,这个修饰器会打印某个函数在收到调用时接受的参数以及返回值
def trace(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print('func_name:{}, args:{}, kwargs:{}, reulst:{}'.format(func.__name__, args, kwargs, result))
return result
def wrapper
之后我们可以使用@
符号来使用这个修饰器
@trace
def fibonacci(n):
"""Return the n-th Fibonacci number"""
if n in(0, 1):
return n
return fibonacci(n-2) + fibonacci(n-1)
#效果等同于 trace(fibonacci)
>>>
fibonacci((1,), {}) -> 1
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((3,), {}) -> 2
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((1,), {}) -> 1
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((3,), {}) -> 2
fibonacci((4,), {}) -> 3
fibonacci((5,), {}) -> 5
上面的修饰器可以正常运作,使用@
符号来修饰函数,效果就等于以该函数为参数,调用修饰器,然后把修饰器所返回的结果,赋给同一个作用域中与原函数同名的那个变量。
通常我们使用functools
模块中名为wraps
的辅助函数来解决,它本身是一个修饰器,将wraps
修饰器运用到wrapper
函数之后,它就会把与函数内部相关的重要元数据都复制到外围函数。
相比于普通函数,装饰器的效果有
- 代码复用:抽象出通用功能,然后应用到多个函数上
- 增强功能:装饰器通常做一些日志记录、权限检查、性能计时的工作
- 清晰简洁:通过修饰器,可以使代码更清晰、易读、避免重复代码
转载自:https://juejin.cn/post/7404776486707544098