栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python工程代码学习笔记(随时更新)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python工程代码学习笔记(随时更新)

1.python格式化输出print的format用法

"{被替换变量0}......{被替换变量1}......".format(变量0,变量1)变量可以是任意类型的

name = "Jack"
num = 1
print("{0}有{1}个书包".format(name,num))

当然format不仅仅可以用于print,还可以直接作用在字符串,例如:

"cfgs/{}_ls.yml".format(args.net)

2.assert函数:判断条件是否为真,如果为真则继续运行程序,如果为假则结束程序并抛出异常AssertionError

用法:assert 表达式 [, 参数]    判断表达式是否为真,如果为假则抛出AssertionError,参数为AssertionError的参数,例如:

a = 1
b = 2
assert a==b,"a不等于{}".format(b)

如果a不等于b,则抛出AssertionError并且其参数为:a不等于b(2),并且程序中断

Traceback (most recent call last):
  File "C:/Pycharm/PycharmProjects/Project_test_1/test.py", line 35, in 
    assert a==b,"a不等于{}".format(b)
AssertionError: a不等于2

3.Python的装饰器与静态装饰器

当我们定义一个类class的时候,第一个参数总是self,类的方法method也有self这个参数。当我们通过实例调用方法obj.method时,我们默认把实例obj本身作为参数传到了方法内。举个例子

 在haha这个类中,x方法有self这个参数,在使用obj.method的时候会自动把obj当做参数来输入x方法。如果我们运行下面这个代码,结果如下:

 

我们实例化c之后,调用c.x()的时候自动把c这个实例作为参数给传到x方法内了。因此相当于多传入了一个参数

解决方法:在方法前面添加@staticmethod

 再添加静态装饰器后,方法x就相当于普通的函数,使用obj.method时不会把实例c当作参数传入方法x内。除了使用静态方法之外,还可以直接用类直接调用方法来做:通过类直接访问方法,即haha.x()。这样也不会把实例当作参数传入到方法x内部。

下面我们来聊一聊装饰器(Decorator):

Python中装饰器是用来修饰或装饰一个已经定义好的函数,例如它可以让你在函数的运行前后做一些其它的事情。而装饰器的本质是一个二阶函数。

首先在Python中所有元素都是看作是对象,甚至是函数。我们可以在其它的函数内定义新的函数,也可以在其它函数返回另一个函数,也可以将其它函数作为参数传到另一个函数内。我们来看一个例子:

def func_1():
    print("你正在函数1内")

def func_2(func_1):

    def func_3():
        print("你正在函数3内")

    print("你正在函数2内")
    func_1()
    return func_3

a = func_2(func_1)
print("执行完了函数2")
print(a)
print(a())
输出为:
你正在函数2内
你正在函数1内
执行完了函数2
.func_3 at 0x00000190459BF700>
你正在函数3内

在执行函数2的时候,按照顺序输出函数2与函数1,然后将返回的函数3的地址赋值给a,我们输出a发现输出的是函数的地址func_3,只有输出a()的时候才相当于输出func_3()才会执行函数内容。

下面我们通过例子来说明一下装饰器的作用:让函数执行前后做一些其它的事情

def func():
    print("执行函数")

def decorator(func):

    def func_1():
        print("执行函数前要做的")
        func()
        print("执行函数后要做的")

    return func_1

func()
func = decorator(func)
func()
输出为:
执行函数
执行函数前要做的
执行函数
执行函数后要做的

我们定义了一个装饰器decorator,它传入的参数是func。在装饰器内部我们定义了一个新的函数func_1:在func执行前后做事情,并且装饰器返回新的函数。通过装饰器修饰前后,我们可以发现输出也会相应地改变。实际上在经过修饰后,func已经变成了func_1。装饰器必须返回一个新的函数,否则无法幅值给func。当然,上面这段代码可以用一种更加简洁的方式:

def decorator(func):

    def func_1():
        print("执行函数前要做的")
        func()
        print("执行函数后要做的")

    return func_1

@decorator
def func():
    print("执行函数")

func()
输出:
执行函数前要做的
执行函数
执行函数后要做的

我们在func前面加了一个@decorator符号,其作用就是代替语句:func = decorator(func)。这样func输出的直接就是被装饰器修饰后的函数。这就是装饰器的作用啦。

Python中还有一个装饰器叫作@property 其作用是创建一个只读的属性。没错,property是一个用于类内方法的装饰器,其作用是创建一个属性。它会自动把一个方法变成一个只读的属性,例:

class DataSet(object):
  @property
  def method_with_property(self): ##含有@property
      return 15
  def method_without_property(self): ##不含@property
      return 15

l = DataSet()
print(l.method_with_property) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
print(l.method_without_property())  #没有加@property , 必须使用正常的调用方法的形式,即在后面加()
与所定义的属性配合使用,这样可以防止属性被修改
class DataSet(object):
    def __init__(self):
        self._images = 1
        self._labels = 2 #定义属性的名称
    @property
    def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
        return self._images 
    @property
    def labels(self):
        return self._labels
l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

4.from __future__ import

这样的做法的作用就是将新版本的特性引进当前版本中。比如我的代码的运行环境时python2的版本,但是我又想体验python3版本的某些功能或者函数,那么我就可以使用这个功能。例如print函数在Python2与Python3的写法不同:

# python 2.x
print "Hello World"
 
# python 3.x
print("Hello World")

如果我们想提前体验Python3的print函数,就可以采用这个写法:

# python 2.x
from __future__ import print_function
print("Hello World")

有的时候我们还会看到absolute_import,这主要是针对Python2.4版本之前的:在Python2.4之前,当我们import一个模块时会优先从当前目录进行导入(比如我们在当前目录自己实现了一个函数print,那么我们导入print的时候就不会导入python自带的print函数而是导入我们自己定义的)。如果我们想用python自带的就必须使用:

from __future__ import absolute_import

5.关键字参数与非关键字参数

我们在python的代码中经常可以看到函数的参数是(*args,**kw)

  • *args是可变参数,args接收的是一个tuple
  • **kw是关键字参数,kw接收的是一个dict

args代表的是可变参数:参数的个数是不确定的可变的,可以是0个、1个、2个......

定义:可变参数就是传入的参数个数是可变的,可以是0个,1个,2个,……很多个。
作用:就是可以一次给函数传很多的参数
特征:*args
首先定义一个可变参数的求和函数:
def cout(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

显然numbers是一个元组或者列表,我们通过元组或列表的方式实现可变参数,但是使用的时候必须要加中括号或者小括号
输出:
>>> cout([1, 2, 3])     参数为列表
14
>>> cout((1, 3, 5, 7))  参数为元组
84

如果我们不想输出的时候还要写小括号或者中括号,可以使用非关键字参数:

在函数的参数前面加上*代表可变参数
def cout(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
这样输出就可以不需要采用元组或者列表,变为:
>>> cout(1, 2, 3)
14
>>> cout(1, 3, 5, 7)
84
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:把列表拆成元素
>>> nums = [1, 2, 3]
>>> cout(nums[0], nums[1], nums[2])
14
这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:
>>> nums = [1, 2, 3]
>>> calc(*nums)
在这里nums还是一个列表,因此体会我们在最开头所说的args接受一个列表或者元组的含义。实际上args还是一个列表,采用*args把这个列表转换成了可变的非关键字参数,传递到函数中

*nums表示把nums这个list的所有元素转换成可变参数传给*args,args获得一个列表。*运算符的这个作用非常常见。注意函数内部的numbers与函数参数的nums都是列表,只有*nums以及*numbers是可变非关键字参数。

kw代表的是关键字参数(keywords):参数的个数也是可变的,但是必须与字典的形式相同:key:value

定义:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。在调用函数时,可以只传入必选参数。
作用:扩展函数的功能
特征:**kw

实例:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:
>>> person(‘Michael’, 30)
name: Michael age: 30 other: {}

也可以传入任意个数的关键字参数:
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

关键字参数有什么用?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

和可变参数*args类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

当然,上面复杂的调用可以用简化的写法:使用**extra
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

**extra与*args对应,表示把extra这个dict的所有key-value用关键字参数转换成关键字参数,再传入到函数的kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。

6.Python的zip函数

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

举个例子:在pytorch训练中,dataset所构成的数据集是由N个元组构成的,每个元组含有两个元素:图片以及其对应的标签(image,label)。我们在训练的时候希望把图片单独放在一起,把标签单独放在一起,构成两个元组[(images),(labels)]放在一个列表内,就可以使用zip函数。

以下实例展示了 zip 的使用方法:

>>>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)]
*zipped是将zipped列表转化为可变非关键字参数(1,4),(2,5),(3,6)共3个元素
相当于zip((1,4),(2,5),(3,6))  zip把所有列表或者元组的第一个元素取出来拼在一起构成新列表的第一个元素,把所有列表或者元组的第二个元素取出来拼在一起构成新列表的第二个元素......以此类推
因此把1,2,3单独取出来构成第一个元素,再把4,5,6单独取出来构成第二个元素
即[(1, 2, 3), (4, 5, 6)]

考虑我们的例子,设batch由N个元组构成,每个元组含有两个元素,分别为图片以及标签,我们就可以使用zip(*batch):首先将batch构成可变非关键字参数,即分解为N个元组,zip将每个元组的第一个元素(图片)取出来,构成第一个元素(N个图片构成的元组);再将每个元组的第二个元素(标签)取出来,构成第二个元素(N个标签构成的元组)。

7.sys.path.append

8.argparser

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/313602.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号