zl程序教程

您现在的位置是:首页 >  后端

当前栏目

py学习(函数,类和对象)

对象学习 函数 py
2023-06-13 09:11:57 时间

函数

• 第五章 函数 • 函数简介(function) • 函数也是一个对象 • 对象是内存中专门用来存储数据的一块区域 • 函数可以用来保存一些可执行的代码,并且可以需要时,对这些语句进行多次的调用 • 创建函数: def 函数名 (【形参1,形参2】) : 代码块 • 函数中保存的代码不会立即执行,需要调用函数代码才能执行 • 参数传递的方式 • 定义形参时,可以为形参指定默认值 • 指定了默认值以后,如果用户传递了参数则默认值没有任何作用 • 如果用户没有传递,则默认值生效 • def fn( a=5,b=10,c=20) • 实参的传递方式 • 位置参数 • 位置参数就是将对应位置的实参赋值给对应位置的形参 • 第一个实参复制给第一个形参,第二个实参赋值给第二个形参 • 关键字参数 • 关键字参数,可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数 • fn(b=1,c=2,a=3) • 实参的类型 • 函数在调用时,解析器不会检查实参的类型 • 不定长参数 • 定义一个函数,可以求任意个数字的和 • Def sum(a,b): • print(a+b) • 在定义函数时,可以在形参前边加上一个*,这样这个形参将会获取到所有的实参 • 它会将所有的实参保存到一个元组中 • Def fn(*a) : • 代码块 • *a会接收所有的位置的实参,并且把这些实参同意保存到一个元组中(装包) • 带星号的形参只能有一个 • 带星号的参数,可以和其他参数配合使用 • 可变参数不是必须写在最后,但是注意,带*号的参数后面的所有参数,必须以关键字参数的形式传递 • 参数的解包 • 传递实参时,也可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数 • 这里要求序列元素的个数必须和形参的个数一致 • 通过**对一个字典进行解包操作 • 返回值 • 返回值,就是函数执行以后返回的结果 • 可以通过return来指定函数的返回值 • 可以之间使用函数的返回值,也可以通过一个变量来接收函数的返回值 • rentun后边可以跟任意的对象,也可以是一个函数 • 如果仅仅写一个return,或者不写return,则相当于 return none • 在函数中,renturn后边的代码都不会执行,return一旦执行,函数自动结束 • 文档字符串 • help()时pythin中的内置函数 • 通过help()函数可以查询python中的函数的用法 • 语法 : help(函数对象) • help(print) 获取print()函数的使用说明 • 文档字符串(doc str) • 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是函数的说明 • 当我们编写了文档字符串时,就可以通过help()函数来查看函数的说明 • 文档字符串非常简单,其实在函数的第一行写一个字符串就是文档字符串 • 作用域 • 作用域指的时变量生效的区域 • 在python中一共有两种作用域 • 全局作用域: • 在程序执行时创建,在程序执行结束时销毁,所有函数以外的区域都是全局作用域 • 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问 • 函数作用域 : • 函数作用域在函数调用时创建,在调用结束时销毁 • 函数每调用一次就会产生一个新的函数作用域 • 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问 • 变量的查找 : • 当我们使用变量时,会优先在当前作用域中寻找变量,如果有则使用,如果没有则继续去上一级中作用域寻找 • 在函数中为变量赋值时,默认都是为局部变量赋值 • 如果希望在函数内部修改全局变量,则需要使用global关键字,来声明变量 • Global a 声明在函数内部使用a时全局变量,此时再去修改a时,就是在修改去全局的a • 命名空间(namespace) • 命名空间指的时变量存储的位置,每一个变量都需要存储到指定的命名空间当中 • 每一个作用域都会有一个它对应的命名空间 • 全局命名空间,用来保存全局变量。函数命名空间用来保存函数中的变量 • 命名空间实际上就是一个字典,是一个专门用来存储变量的字典 • locals() • 用来获取当前作用域的命名空间 • 如果在全局作用域中调用locals()则获取全面命名空间, • 返回的是一个字典 • scope=locals() #当前命名空间 • 在函数内部调用locals()则会获取函数的命名空间 • globals()函数可以用来在任意位置获取全局命名空间 • 递归 • 递归式的函数,在函数中自己调用自己 • Def fn(): • fn() • 无穷递归,如果这个函数被调用,程序的内层会溢出,效果类似于死循环 • 递归式函数的两个要件 • 1基线条件,问题可以被分解为的最小问题,当满足基线条件时,递归就不再执行了 • 2 递归条件 ,将问题继续分解的条件 • Def fn(n): • if n == 1: • renturn 1 • renturn n*fn(n-1) • 递归和循环类似,基本是可以互相代替 • 高阶函数 • 在python中,函数是一等对象 • 一等对象有如下特点 • 1 对象是在运行时创建的 • 2 能赋值给变量或者作为数据结构中的元素 • 3 能作为参数传递 • 4 能作为返回值返回 • 高阶函数 • 高阶函数至少要符合一下两个特点中的一个 • 1 接受一个或多个和函数作为参数 • 2 将函数作为返回值返回 • 当我们传递一个函数时,其实是传递函数中的代码 • 匿名函数 • filter() • 可以从序列中过滤出符合条件的元素,保存到一个新的序列中 • 参数: • 1 函数,根据函数来过滤序列(可迭代结构) • 2 需要过滤的序列(可迭代结构) • 返回值: 过滤后的新序列(可迭代结构) • 匿名函数 lamda 函数表达式 • Lamda函数表达式专门用来创建一些简单的函数,他是函数创建的又一种方式 • 语法 : lambda 参数列表 : 返回值 • Def fn(a,b) : • renturn a+b • Lambda a,b : a+b • 可以将匿名函数赋值给一个变量,一般不会这么用 • map() • 可以对可迭代对象中的所有元素做指定的操作,然后将其添加到一个新的对象中返回 • r= map((lambda I : i+1),list) • Sort • 该方法用来对列表中的元素进行排序 • sort()方法默认是直接比较列表中的元素的大小 • 在sort()中可以接受一个关键字参数,key • key需要一个函数作为参数,当设置了函数作为参数,每次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素的大小 • sort(key=len)或sort(key=int) • sorted() • 这个函数和sort()的用法基本一致,但是sorted()可以对任意的序列进行排序 • 并且使用sorted()不会影响之前的序列,而是返回一个新序列 • 闭包 • 将函数作为返回值返回,也是一种高阶函数 • 这种高阶函数我们也称为叫做闭包,通过闭包可以创建一些只有当前函数能访问的变量 • 可以将一些私有的数据隐藏闭包中 • 形成闭包的要件 • 1函数嵌套 • 2将内部函数作为返回值 • 3内部函数必须要使用外部函数的变量 • Def fn(): • #函数内部再定义一个函数 • def fn2() : • print(xxx) • #将内部函数fn2作为返回值返回 • renturn fn2 • r= fn() • r() • r是一个函数,是调用fn()后返回的函数 • 这个函数是在fn()内部定义,并不是全局函数 • 所以这个函数总是能访问到fn()函数内的变量 • 装饰器引入 • 希望函数可以在计算前,打印开始计算,计算结束后打印计算完毕 • 我们可以直接通过修改函数中的代码来完成这个需求,但是会产生以下一些问题 • 1 如果要修改的函数过多,修改起来会比较麻烦 • 2 并且不方便后期的维护 • 3 并且这样做会违反开闭原则(ocp) • 程序的设计,要求开发对程序的扩展,要关闭对程序的修改 • 我们希望在不修改原函数的情况下,来对函数进行扩展 • 只需根据现有的函数,来创建一个新的函数 • Def fn2() : • print(xxx) • fn • print(xxx) • 现在只需调用fn2 • 装饰器的使用 • 上边的方式,已经可以在不修改源代码的情况下对函数进行扩展了 • 但是,这种方式要求我们,每扩展一个函数就要手动创建一个新的函数,很麻烦 • 为了解决这个问题,我们创建一个函数,让这个函数可以自动地帮助我们生产函数 • Def begin_end(old) : • ”’ • 用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束 • 参数: old 要扩展的函数对象 • ”’ • def new_function(*args,**kwargs): • print(xxx) • #调用被扩展的函数 • result= old(*args,**kwargs) • print(xxx) • return result • renturn new_function • f=begin_end(fn) 将fn函数装饰为f • r=f() • 比如bengin_end()这种函数,我们称为装饰器 • 通过装饰器,可以在不修改原来函数的情况下对函数进行扩展 • 在开发中,我们都是通过装饰器来扩展函数的功能 • 在定义函数时,可以通过@装饰器,来使用指定的装饰器,来装饰当前的函数,可以同时为一个函数指定多个装饰器,是由内向外装饰 • @begin_end • Def say_hello(): • print(xxx)

类与对象

• 面向对象 • 对象是内层中专门用来存储数据的一块区域 • 对象中可以存放各种数据(比如:数字,布尔值,代码) • 对象由三部分组成: • 1对象的标识(id) • 2对象的类型(type) • 3对象的值(value) • 面向对象 • python是一门面向对象的编程语言 • 所谓的面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的 • 面向过程的编程语言 • 面向过程指将我们的程序的逻辑分解为一个一个的步骤 • 通过对每一个步骤的抽象来完成程序 • 这种编程方式,符合人类的思维,编写起来相对比较简 • 但是可复用性很差 • 面向对象的编程语言 • 面向对象的编程语言,关注的是对象,而不是关注过程 • 对于面写对象的语言来说,一切都是对象 • 面向对象的编程思想,将所有的功能统一保存对应的对象中 • 这种方式编程的代码,便于阅读,便于维护 • 但是这种方式编写,不太符合常规的思维 • 简单归纳一下,面向对象的思想 • 1 找对象 • 2 搞对象 • 类的简介(class) • 目前所学习的对象都是py内置的对象 • 但是内置对象并不能满足所有的需求,所以在开发中经常需要自定义一些对象 • 类,简单理解它就相当于一个图纸,在程序中我们需要根据类来创建对象 • 类就是对象的图纸 • 我们也称对象是类的实例(instance) • 如果多个对象是通过一个类创建的,我们称这些对象是一类对象 • 比如 int() float() bool() str() list() dict() 这些都是类 • a= int(10) #创建一个int类的实例 等价于 a=10 • 我们自定义的类都需要使用大写字母开头,使用大驼峰命名法来对类命名 • 定义一个简单的类 • 使用class关键字来定义类,语法和函数很像 • Class 类名([父类]): • 代码块 • Class myclass() : • pass • 使用myclas创建一个对象 • 使用类来创建对象,就像调用一个函数一样 • mc=myclass() #mc就是用过myclass创建的对象,ma是myclass 的实例 • isinstance() • 用来检查一个对象是否是一个类的实例 • 例如 result= isinstance(mc,myclass) • 对象的创建流程 • 类也是一个对象 • 类就是一个创建对象的对象 • 类是type类型的对象,定义类实际上就是定义了一个type类型的对象 • 创建对象的流程 : 1创建一个变量mc • 2 在内层中创建一个新对象 • 3 将对象的id赋值给变量 • 可以向对象中添加变量,对象中的变量称为属性 • 语法 : 对象. 属性名=属性值 • Mc.name=’孙悟空’ • • 类的定义 • 类和对象都是对现实生活或程序的内容的抽象 • 实际上所有的事物都有两部分构成: • 1 数据(属性) • 2 行为(方法) • 在类的代码块中,我们可以定义变量和函数 • 变量会称为该类实例的公共属性, • 函数会成为该类实例的公共方法 • 方法调用时,第一个参数由解析器自动传递,所有定义方法时,至少定义一个形参 • 定义一个表示人的类 : • class person: • pass #在类的代码块中,我们可以定义变量和函数 • #在类中我们所定义的变量,将会称为所有实例的公共属性, • 所有的实例都可以访问这些变量 • name=’xxx’ #公共属性,所有实例都可以访问 • #在类中也可以定义函数,类中定义的函数,称为方法 • #这些方法可以通过该类的实例来访问 • def say_hello(self): • #方法每次被调用时,解析器都会自动传递第一个实参 • #第一个参数,就是调用方法的对象本身 • #一般我们将这个参数叫做self • print(xxx) • 创建person的实例 • p1=perspn() • p2=person() • 调用方法 : 对象.方法名() • 方法调用和函数调用的区别 • 如果是函数调用,则调用时传几个参数,就会有几个实参 • 但是如果是方法调用,默认传递一个参数,所以方法中至少需要一个形参 • 属性和方法 • 实例怎么访问类中的属性和方法 • 类中定义的属性和方法都是公共的,任何该类的实例都可以访问 • 属性和方法查找的流程 • 当我们调用一个对象的属性时,解析器会在当前对象中寻找含有该属性 • 如果有,则直接返回当前的对象的属性 • 如果没有,则取当前对象的类中去寻找,如果有则返回类对象的属性值 • 如果没有则报错 • 类和实例对象的中都可以保存属性(方法) • 如果这个属性(方法)是所有实例共享的,则应该将其保存到类对象中 • 如果这个属性(方法)是某个实例独有的,则应该保存在实例对象中 • 一般情况下,属性保存在实例对象中,方法保存在类对象中 • 类的特殊方法init • 目前来讲,对于person类来说name时必须的,并且每一个对象中的name属性基本上都是不同的 • 而我没现在是将name属性在定义为对象以后,手动添加对象中,这种方式很容易出现错误 • 我们希望用户在创建对象时,必须设置name属性,如果不设置对象将无法创建, • 并且属性的创建应该时自动完成的,而不是在创建对象以后手动完成 • 在类中定义一些特殊方法 • 特殊方法都是以__方法,__结尾方法 • 特殊方法不需要自己调用,不要尝试去调用特殊方法 • 特殊方法将会在特殊的时刻自动调用 • 1 特殊方法什么时候调用 • 2 特殊方法用什么作用 • 创建对象的流程 • p1=person()的运行流程 • 1 创建一个变量 • 2 在内存中创建一个新对象 • 3 __init__(self)方法执行 • 4 将对象的id赋值给变量 • init会在对象创建以后离开执行 • init可以用来向新创建的对象中初始化属性 • Def__init__(self,name) : • self.name=name • Def say_hello(self) : • print(‘大家好,我是%s’%self.name) • 类的基本结构 • Class 类名(【父类】) : • 公共的属性 • def __init__(self,…) : • 。。。 • def method(self,…) : • 。。。 • 。。。

废江博客 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 转载请注明原文链接:py学习(函数,类和对象)