Python高级

2023-10-18 08:46:11 浏览数 (2)

日常读和写python项目时遇到的常用的高级python知识。

1. import的用法

绝对导入,主要用于导入sys.path的包,以及运行入口文件导入自己的模块。

  1. import module_name
    • Python会在两个地方寻找这个模块,第一是sys.path(通过运行代码import sys; print(sys.path)查看),所以对于安装好的库,我们直接import即可。第二个地方就是运行文件所在的目录。
    • 可以作为module的文件类型有".py"、".pyo"、".pyc"、".pyd"、".so"、".dll"。
    • 当我们向文件导入某个模块时,导入的是该模块中那些名称不以下划线(单下划线“_”或者双下划线“__”)开头的变量、函数和类。
  2. from package_name import module_name
    • 与第一种写法类似,Python会在sys.path和运行文件目录这两个地方寻找包,然后导入包中名为module_name的模块。
    • package_name 指的就是文件夹名,包目录下为首的一个文件便是__init__.py。如果一个模块定义有列表__all__,则from module import * 语句只能导入__all__列表中存在的对象。

相对导入,主要用于非运行入口文件导入自定义模块

  1. from . import module_name
    • 导入和自己同目录下的模块。
  2. from .package_name import module_name
    • 导入和自己同目录的包的模块。
  3. from .. import module_name
    • 导入上级目录的模块。
  4. from ..package_name import module_name
    • 导入位于上级目录下的包的模块。
  5. 当然还可以有更多的.,每多一个点就多往上一层目录。

其他用法

  1. from module_name import function_name, variable_name, class_name
    • 有时候我们只想使用模块中的某些函数、某些变量、某些类,用这种写法就可以了。使用逗号可以导入模块中的多个元素。

2. 定义类

class ClassName(Base1,Base2):在类的定义中,括号中的为父类。__init__ : 构造函数,在生成对象时调用。双下划线开头的为私有属性或私有方法。所有方法的第一个参数都为self

3. __call__

允许一个类的实例像函数一样被调用。实质上说,这意味着 x() 与 x.__call__() 是相同的。

4. __dict__

类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类__dict__里的

对象的__dict__中存储了一些self.xxx的一些东西

一些内置的数据类型是没有__dict__属性的

5. __name__

__name__是python内置的属性。

  • 对于一个python模块来说。当一个py文件自己运行时,__name__就是__main__,当这个文件作为模块被调用时,__name__就是文件的名字。
  • 对于一个类来说,__name__就是类的名字。

6. 装饰器

代码语言:javascript复制
@a_new_decorator
def a_function_requiring_decoration():
    """Hey you! Decorate me!"""
    print("I am the function which needs some decoration to remove my foul smell")

以上代码的意思为

代码语言:javascript复制
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

(其中,a_new_decorator的定义如下)

代码语言:javascript复制
from functools import wraps
def a_new_decorator(a_func):
    @wraps(a_func) # 可以让我们在装饰器里面访问在装饰之前的函数的属性,如参数列表、__name__等
    def wrapTheFunction():
        print("I am doing some boring work before executing a_func()")
        a_func()
        print("I am doing some boring work after executing a_func()")
    return wrapTheFunction

装饰器可以是函数,也可以是类。

详解:https://www.runoob.com/w3cnote/python-func-decorators.html

7. @property

Python内置的@property装饰器就是负责把一个方法变成属性调用的。这样就能既能检查参数,又可以用类似属性这样简单的方式来访问类的变量(而不需要调用set和get方法)。

使用:把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值。还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。

代码语言:javascript复制
class Student(object):
    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

# 运行结果
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

8. *args 和 **kwargs

当函数的参数数量不确定时,可以使用*args 和**kwargs,*args 没有key值,**kwargs有key值。

*args 可以接收元组(tuple),**kwargs可以接收字典。

代码语言:javascript复制
def test_var_args(f_arg, *argv):
    print("first normal arg:", f_arg)
    for arg in argv:
        print("another arg through *argv:", arg)

>>> test_var_args('yasoob', 'python', 'eggs', 5)
# 结果
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: 5

# 接收元组
args = ('python', 'eggs', 5)
test_var_args('yasoob',*args)
代码语言:javascript复制
def greet_me(**kwargs):
    for key, value in kwargs.items():
        print("{0} == {1}".format(key, value))

>>> greet_me(arg1=5,arg2="two")
arg1 == 5
arg2 == two

# 接收字典
kwargs = {"arg1": 5, "arg2": "two"}
greet_me(**kwargs)

9. partial函数

该函数的形式:

functools.partial(func[,*args][, **kwargs])

示例:

代码语言:javascript复制
from functools import partial
def multiply(x, y):
    return x * y
double = partial(multiply, y=2)

partial 接收函数 multiply 作为参数,固定 multiply 的参数 y=2,并返回一个新的函数给 double。

简单而言,partial 函数的功能就是:把一个函数的某些参数给固定住,返回一个新的函数。

10. map函数

map()是 Python 内置的高阶函数,它接收一个函数 functon 和一系列可迭代对象(list, set, dir, tuple, str等),并通过把函数 function 依次作用在 iterable 的每个元素上,得到一个新的 map对象(map object at …)并返回。对于新的map对象,可用list(map_obj)或tuple(map_obj)转化为想要的数据类型。 示例:

代码语言:javascript复制
def square(x) :            # 计算平方数
    return x ** 2

>>>map(square, [1,2,3,4,5])   # 计算列表各个元素的平方
[1, 4, 9, 16, 25]

11. zip函数

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。

示例:

代码语言:javascript复制
>>>a = [1,2,3]>>> b = [4,5,6]>>> c = [4,5,6,7,8]>>> zipped = zip(a,b)     # 打包为元组的列表[(1, 4), (2, 5), (3, 6)]>>> zip(a,c)              # 元素个数与最短的列表一致[(1, 4), (2, 5), (3, 6)]>>> zip(*zipped)          # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式[(1, 2, 3), (4, 5, 6)]

12. Typehint

typehint指为函数的参数和返回值设置数据类型。为函数写上typehint不仅可以增加代码的可读性,结合mypy进行静态类型检查还可以增加代码的鲁棒性。 对于输入类型的typehint,提供以下示例:

代码语言:javascript复制
from typing import Union
from typing import Optional
a: int = 1
b: float = 0.5
c: Union[int, float] = 0.5
l: List[int] = [1, 2]
t: Tuple[int, int] = (1, 2)
n: Optional[str] = None  # 除了None,只能是str
func: Callable   # 参数为可调用的函数

对于返回值的typehint,示例如下:

代码语言:javascript复制
def myadd(a: int, b: int) -> int:
    return a b

13. 数组切片

除了数字、冒号之外,数组的索引还可以是None,None代表新增加一个维度,None放在哪一维,就会在哪一维上出现新的维度。

...只能用于numpy的数组,而不能用于python自带的list

它是省略所有的冒号来用省略号代替,a[:, :, None]和a[…, None]的输出是一样的,就是因为…代替了前面两个冒号。

0 人点赞