Python和Numpy高级

Python高级

日常读和写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. 装饰器

1
2
3
4
@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")

以上代码的意思为

1
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

(其中,a_new_decorator的定义如下)

1
2
3
4
5
6
7
8
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方法就是一个只读属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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可以接收字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)
1
2
3
4
5
6
7
8
9
10
11
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])

示例:

1
2
3
4
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)转化为想要的数据类型。
示例:

1
2
3
4
5
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() 转换。

示例:

1
>>>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. 数组切片

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

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

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

numpy或pytorch

1. repeat函数

使用方式:

1
numpy.repeat(a,repeats,axis=None)object(ndarray).repeat(repeats,axis=None)

可以将numpy array在axis方向复制repeats次。repeats可以是数字或者列表。

axis=None,时候就会flatten当前矩阵,实际上就是变成了一个行向量。

axis=0,沿着y轴复制,实际上增加了行数。

axis=1,沿着x轴复制,实际上增加列数。

示例:

1
>>> import numpy as np>>> c = np.array([[1,2],[3,4]])>>> print(c)[[1 2] [3 4]]>>> np.repeat(c,2)array([1, 1, 2, 2, 3, 3, 4, 4])>>> np.repeat(c,2,axis=1)array([[1, 1, 2, 2],       [3, 3, 4, 4]])>>> np.repeat(c,2,axis=0)array([[1, 2],       [1, 2],       [3, 4],       [3, 4]])>>> np.repeat(c,[2,3],axis=0)array([[1, 2],       [1, 2],       [3, 4],       [3, 4],       [3, 4]])

2. permute函数

pytorch的函数:TensorName.permute(多维数组, [维数的组合]),可以实现维度的交换

示例:

1
import torchimport numpy as np a=np.array([[[1,2,3],[4,5,6]]]) unpermuted=torch.tensor(a)print(unpermuted.size())  #  ——>  torch.Size([1, 2, 3]) tensor([[[1., 4.],        [2., 5.],        [3., 6.]]])  permuted=unpermuted.permute(2,0,1)print(permuted.size())     #  ——>  torch.Size([3, 1, 2]) tensor([[[1., 2.],         [3., 4.],         [5., 6.]]])

请我喝杯咖啡吧~

支付宝
微信