(四)python语法之代码复用

当代码相同的时候,我们可以选择直接将代码复制,这样的话,虽然简单,但是这样子会留下隐患,其一是代码修改起来很繁琐,比如相同的代码出错了,就要都修改掉。其二是很容易留下bug,因为你的逻辑会混乱。这样子写代码,很不适合代码的顺序结构。因此我们要采用一些方法,来增加代码的复用性。分别是类与函数。

函数

函数的定义与调用

函数的定义很简单,只要使用def关键字就可以了。

def func():
	pass

调用函数也很简单,只要调用函数名就可以了。

函数的参数

函数占用一块内存区域,所以如果想和代码主体进行变量共享,参数是一种蛮不错的方式,这里参数是分为了普通参数,默认参数,可变长参数,关键字参数。但是在说参数之前还要说明一下,什么是代码的实参?什么是代码的形参?实参就是在函数调用中,放到函数中的变量,为什么叫做实参数?因为是实际存在的变量,这个实际参数是有指向的内存空间。而形参,是逻辑上存在的,在函数定义的时候,并没有内存空间分配给形参,所以是形式参数,是逻辑上存在。

普通参数

普通参数就是最普通的参数,就像变量一样.如下面这个例子。

>>> def func(x,y):
...     print(x,y)
...
>>> func(1,2)
1 2

但是普通参数使用的时候,要注意一些事情,就是形参与实参位置要一一对应,就像上面这个例子,x1 ,y2。当然如果不想要一一对应,就要在代码调用的时候,进行限制

>>> def func(x,y):
...     print(x,y)
...
>>> func(1,2)
1 2
>>> func(x=2,y=1)
2 1

这样子有什么好处就是,不用管参数的位置,否则,你可以设想一下,你调用函数,还要管参数的位置,那将多么繁琐。

默认值参数

默认值参数就是在函数定义的时候,指定形参的值,这样子可以简化函数。

>>> def func(x,y=1):
...     print(x,y)
...
>>> func(2)
2 1

但是默认值参数有基地啊注意点

  • 默认值参数只能放在普通的最右边,否则就会报错;
  • 默认值参数可以有多个;

可变长参数

可变长参数,简单的就是将一个元组传递到参数里面,这样子的话就可以不用限制参数的个数。定义方式,在参数前面用“*”

>>> def func(*numble):
...     print(numble)
...
>>> func(1,2,3,4,5,6,7,8,9)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

如上,可以看出numble就是可变长参数,这个参数就是将1,2,3,4,5,6,7,8,9封装成(1,2,3,4,5,6,7,8,9)的元组。

关键词参数

可变长参数很好,但是我们要引用的时候,只能用下标来引入,这样子的话,比较丑,而且你不能控制传入的参数。所以我们就需要关键词参数,这个关键词参数就是传入后变成字典形式

>>> def func(**member):
...     print(member)
...
>>> func(class1="Tom",class2="Fony",class3="Sonny")
{'class1': 'Tom', 'class2': 'Fony', 'class3': 'Sonny'}

当然你也可以控制传入的参数名字,只要修改一下就可以了

>>> def func(*,class1,class2,class3):  这里参数定义的时候修改了一下
...     print(class1,class2,class3)
...
>>> func(class1="Tom",class2="Fony",class3="Sonny")
Tom Fony Sonny
>>> func(class4="Tom",class5="Fony",class6="Sonny")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() got an unexpected keyword argument 'class4'

参数组合

我们使用参数的时候,肯定不可能只用一种参数,肯定是多种参数一起使用,那么参数之间的排列顺序是什么?

>>>def f1(a, b, c=0, *args, **kw):
...     print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

>>>def f2(a, b, c=0, *, d, **kw):
...     print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

变量作用区域

变量器作用的额代码范围称为变量的作用与,不同作用区域之间互不影响,函数每部定义的变量一般为局部变量,而不属于任何函数的变量一般为全局变量。所以我们在这里按变量的作用区域分为两类,全局变量和局部变量(这里的局部变量就指的是函数中创建的变量)

在函数中使用全局变量

很简单,直接使用。但是这里在函数中修改全局变量,并不会对全局变量产生影响,那么怎么样才能在在函数中改变全局变量的值
这里分为两部分,第一部分就是可迭代对象的修改,可迭代对象可以直接在函数中修改,而这个已经影响到了全局的可迭代对象,如下

>>> a=[1,2,3]
>>> def test():
...     print(a)
...     a.append(4)
>>> test()
[1, 2, 3]
>>> print(a)
[1, 2, 3, 4]

可以看出不用对变量最任何改变就能够在函数中修改可迭代对象。
第二部分就是只能单个使用的变量,所以就需要用到global关键字。

>>> x=2
>>> def test():
...     global x
...     print(x)
...     x=4
>>> test()
2
>>> print(x)
4

那么,现在就很好奇了,如果不用关键词,能使用全局变量呢?应该不能,为什么?会爆粗
UnboundLocalError: local variable ‘x’ referenced before assignment
那么如果局部变量与全局变量具有相同的名字的话,那么改局部变量会在自己的作用域会隐藏同名的全局变量。

生成器

生成器函数和普通的函数一样,不过多了一些功能,和有一些不一样,最大的不一样是使用yield关键字返回值,而不是通过return.而存在时间也与普通得到函数存在时间不一样,普通的函数在函数执行完毕,就会释放这个函数所占用的内存空间。而生成器函数则是不一样,需要手动销毁。生成器的强大之处,在于你不用等到函数全部执行完毕的时候返回,你啥时候想返回都可以,比如你需要读取1个G的文本,如果不用生成器,你就要全部读完,再返回。而有了生成器后,你只要需要的时候就返回一行数据,不需要就不执行生成器。

生成器关键词

  • yield ,这个就是返回一个值,但是返回值后,生成器就停止了,直到收到指令会继续执行yield的下一行语句;
  • next,这个是获取生成器生成的值即generator().next()。执行一次这个语句就会收到一个值。
  • send(),这个是加强与generator的交互,使用这个你可以将变量传入到生成器里面去;
  • close(),这个就是关闭生成器。就是释放生成器所占用的内存;

类就是另外一个可以提高代码复用性的另外一个方式。这里只是归纳一下,我学到的,所以很少

类的定义

类的定义就是使用关键字class

class ClassName():
	pass

这个就是类的定义方式

类的方法

类的方法分为五类,分别是公有方法,私有方法,静态方法,类方法和魔法方法。下面用一个例子来介绍这些方法。

class Methods():
	def __init__(self):  
			print(" 魔法方法")
	def show(self):
			print('这个是公有方法')
	def __private__(self):
			print("这个是私有方法")
	@classmethod
	def classShow(cls):
			print("这个是类方法")

	@staticmethod
	def staticShow():
			print("这个静态方法")
	```
对这个方法进行调用

```python
>>> object=Methods()
魔法方法
>>> object.show()
这个是公有方法
>>> Methods.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: show() missing 1 required positional argument: 'self'
>>> object.__private__()
这个是私有方法
>>> Methods.__private__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __private__() missing 1 required positional argument: 'self'
>>> object.classShow()
这个是类方法
>>> Methods.classShow()
这个是类方法
>>> object.staticShow()
这个静态方法
>>> Methods.staticShow()
这个静态方法

从上面这个例子中,我们可以知道公有方法和私密方法类是不能直接访问的只有实例化之后,才能够访问。
而静态方法与类方法。之间有共同点也有不同点
共同点

  • 都是不用实例化,直接用类就能够访问;
  • 都不需要self
    不同点
  • 装饰器不同,类方法使用classmethod,而静态方法则是使用staticmethod;
  • 参数不同,类方法还需要cls,而静态方法不需要任何参数;

类的属性

类的属性这里是分为了两部分,静态属性和动态属性,静态属性很简单,self.xx=就能够定义。动态属性,这里则是将方法变成了属性,也很简单,只要用@property装饰器就可以了

class Methods():
    @property
    def variable_name(self):
        
        return '动态属性'

当然动态属性需要返回一个值,而且动态属性不能修改,只可读。

类的继承

类的继承很简单,看一个例子就可以了。

class Methods():
    def __init__(self,Parent_args):
        print(" 魔法方法")
    def show(self):
        print('这个是公有方法')
    def __private__(self):
        print("这个是私有方法")
    @classmethod
    def classShow(cls):
        print("这个是类方法")

    @staticmethod
    def staticShow():
        print("这个静态方法")

class MyMethod(Methods):
    def __init__(self,child__args1,child__args2):
        Methods.__init__(child__args2)
            pass

猜你喜欢

转载自blog.csdn.net/qq_41861526/article/details/82890722
今日推荐