• 欢迎访问废江's博客 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏本站吧

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

python 站点默认 1个月前 (11-13) 22次浏览 已收录 0个评论
文章目录[隐藏]

函数

• 第五章 函数
• 函数简介(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学习(函数,类和对象)
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到