Python函数

文章目录

一、函数基本语法

二、高阶函数

三、装饰器

四、包和模块

五、面向对象

Python 函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码块。它们提高了代码的可读性和可维护性,使得代码更加模块化。

一、函数基本语法

1.1 函数概述

在一个完整的项目中,某些功能可能会被反复使用,如果将反复出现的代码封装成函数,以后如果要继续使用该功能则直接使用函数即可,另外,如果要修改需求,只需要修改函数即可。

本质:对某些特殊功能的封装,使用函数的三大优点:代码重用、保持一致性、可扩展性。

1.2 函数定义和调用

使用def关键字来定义一个函数,函数名后面跟着圆括号,圆括号中可以包含参数,然后是冒号:,最后是函数体(缩进的代码块)。

语法:

def 函数名(变量1,变量2....):

函数体

return 返回值

函数定义四种方式(无参无返回值、有参无返回值、无参有返回值、有参有返回值)

python 复制代码
print('start')
# 1.无参无返回值
def func1():
	print('ok~~~11111')

# 2.有参无返回值
def func2(a,b):
	print('ok~~~~~2222',a,b)

# 3.无参有返回值
def func3():
	print('ok~~~33333')
	return  'abc'

# 4.有参有返回值
def func4(num1,num2,num3):
	print('ok~~~~~4444',num1,num2,num3)
	return num1 + num2 + num3
print('end')

函数调用语法:通过 函数名()即可完成调用

每次函数调用时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用结束了,如果函数中执行到了return也会结束函数。

python 复制代码
def f1():
	f2()
	print('1111')
def f2():
	print('222222')
	f3()
def f3():
	print('333333')
1.3 函数参数

在Python函数中,参数可以分为多种类型,包括必须参数、默认参数、关键字参数和不定长参数:

|-------------------|-------------------------|---------------------------------------------------------------------------|
| 参数类型 | 描述 | 示例 |
| 必须参数 | 函数调用时参数的顺序必须和定义时一致 | def func(a, b): return a + b |
| 默认参数 | 如果没有传递参数,则使用定义函数时指定的默认值 | def func(a, b=2): return a + b |
| 关键字参数 | 允许按照参数名传递参数,不需要考虑参数的顺序 | def func(a, b): return a + b 调用时:func(b=3, a=1) |
| 不定长参数(*args) | 参数在函数内部作为元组处理 | def func(*args): return sum(args) |
| 不定长参数(**kwargs) | 用于传递一个不定长度的关键字参数字典给函数 | def func(**kwargs): for key, value in kwargs.items(): print(key, value) |

值传递 :传参的时候,传递的是不可变的数据类型,如:int/float/str/tuple/bool,当形参发生修改,对实参没有影响。

引用传递 :传参的时候,传递的是可变的数据类型,如:list/dict/set等,当形参中的元素发生修改,则实参会随着修改。

1.4 返回值

返回值:表示函数的运算结果,在哪里调用函数,返回值就返回到哪里,函数返回值语法结构如下:

def 函数名(形参):

函数体【某个功能】

return 返回值

Python中return、break、exit()区别如下:

|--------|--------------------|------------------|----------|
| 分类 | 用途 | 说明 | 终止级别 |
| return | 从函数返回一个值给调用者 | 可以是任何类型(包括None) | 函数 |
| break | 跳出当前循环(如for、while) | None(不返回值,但结束循环) | 循环 |
| exit() | 退出Python程序 | 表示退出状态码,默认为0 | 程序 |

1.5 匿名函数

匿名函数为不再使用def这种标准形式定义函数,而是使用lambda表达式来创建函数,该函数没有函数名,被称为匿名函数。

匿名函数语法:lambda 形参列表:返回值

lambda函数的特点:

1简洁性:对于简单的函数,使用lambda可以使代码更加简洁。

2匿名性:lambda函数没有名称。

3函数对象:lambda表达式会生成一个函数对象,可以将其赋值给一个变量,然后通过这个变量来调用它。

python 复制代码
# 标准函数的定义
def f1(n):
print('函数被调用了~~~')
return n + 1
print(f1)   # <function f1 at 0x00000228F1D7F040>
r1 = f1(6)  # 函数的调用
print(r1)   # 函数的返回值

# 匿名函数/lambda表达式,语法:lambda  形参列表:返回值
f2 = lambda n: n + 1
print(f2)   # <function <lambda> at 0x000002860924C3A0>
r2 = f2(8)  # 调用函数
print(r2)   # 函数的返回值
1.6 函数嵌套

def func1():

def func2():

xxx

func1:外部函数

func2:内部函数

func1和func2的参数,返回值的使用和最基本的使用完全相同

python 复制代码
# 2.嵌套函数的调用
# 方式一:在外部函数中直接调用内部函数
def func1():
print('外部~~~~11111')
n1 = 10
def func2():
  n2 = 20
  print(n1 + n2)
  print('内部~~~111111')
func2()    # 调用内部函数func2
print('外部~~~~222222')
func1()

# 方式二:将内部函数作为外部函数的返回值返回
def func1():
print('外部~~~~11111')
n1 = 10
def func2():
  n2 = 20
  print(n1 + n2)
  print('内部~~~111111')

print('外部~~~~222222')
1.7 函数闭包

闭包的概念:如果两个函数嵌套定义,如果在内部函数中访问了外部函数中的变量,则构成一个闭包。

闭包的用法分类:内外部函数均无参、外部函数有参、内外部函数有参、内外部函数有参且内部函数有返回值。

python 复制代码
# 闭包:如果两个函数嵌套定义,如果在内部函数中访问了外部函数中的变量,则构成一个闭包   *********
# 闭包的常见写法
# a.内外部函数均无参
def func1():
	n1 = 10
def func2():
  n2 = 20
  print(n1 + n2)
return func2
f = func1()
print('外部函数调用完毕')  # 当外部函数被调用完毕之后,按理n1会被销毁
f()         # 但是,在函数的嵌套定义中,由于内部函数访问了外部函数中的变量,所以当外部函数调用完毕之后,内部函数仍然可以访问到外部函数中的变量

# b.外部函数有参
# a,b和n1都属于外部函数中的变量,只要这三者中的任何一个被func2访问,则都会构成闭包
def func1(a,b):
n1 = 10
def func2():
  n2 = 20
  print(n1 + n2,a,b)
return func2
f = func1(3,2)
f()

# c.内外部函数有参
def func1(a,b):
n1 = 10
def func2(num1,num2,num3):
  n2 = 20
  print(n1 + n2,a,b,num1,num2,num3)
return func2
f = func1(3,2)
f(55,66,77)   # 注意:相当于调用的是func2,所以一定要注意和func2的参数保持匹配

# d.内外部函数有参,内部函数有返回值
def func1(a,b):
n1 = 10
def func2(num1,num2,num3):
  n2 = 20
  print(n1 + n2,a,b,num1,num2,num3)
  return n1 + n2
return func2
f = func1(3,2)
r = f(55,66,77)
print(r)

# 注意:虽然是函数嵌套定义,虽然是闭包,但是内外部函数本质上和普通函数的用发完全相同,默认参数,关键字参数,不定长参数和返回值都一样使用
1.8 变量作用域

变量的作用域指的是变量可以使用的范围,程序的变量并不是在任意位置都可以访问,访问权限取决于这个变量是在哪里定义的,变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

函数变量作用域分类介绍如下:

|-------------------|------------------------------|---------------------|
| 作用域类型 | 描述 | 生命周期 |
| 局部作用域(Local ) | 在函数内部定义的变量,只能在函数内部访问 | 函数调用时创建,函数结束时销毁 |
| 函数作用域(Enclosing ) | 在嵌套函数(内部函数)中访问其外部函数中的变量 | 外部函数调用时创建,外部函数结束时销毁 |
| 全局作用域(Global) | 可以在整个模块中访问,包括在函数内部 | 程序开始时创建,程序结束时销毁 |
| 内置作用域(Built-in) | Python内置的变量和函数,如len(),max()等 | 解释器启动时创建,解释器关闭时销毁 |

1.9 生成器和迭代器

(1)生成器

生成器概念:在Python中,一边使用和一边计算的机制被称为生成器(generator),在代码执行的过程中,大量的内存空间会被节约下来。

生成器定义方式:

a.将列表推导式中的[]改为()

num = (n ** 2 for n in range(10))
print(type(num)) # <class 'generator'>

b.函数结合yield,定义函数生成器

def func1():

yield 10

num = func1()

print(type(num)) #<class 'generator'>

(2)迭代器

可迭代对象(Iterable)可以直接作用于for循环的对象,如:list、tuple、dict、set、str、range()、生成器等;迭代器(Iterator)可以直接作用于for循环且可以通过next()获取下一个元素的对象,如生成器。

迭代器一定是可迭代对象,但是可迭代对象不一定是迭代器,可以通过系统功能iter()将不是迭代器的可迭代对象转换为迭代器。

from collections.abc import Iterable,Iterator

print(isinstance(iter([1,2,5]),Iterator)) # 结果为True

print(isinstance(iter((5,6,7)),Iterator)) # 结果为True

print(isinstance(iter('qwer'),Iterator)) # 结果为True

二、高阶函数

高阶函数是指是指那些可以接收函数作为参数,或者返回一个函数作为结果的函数。常用的高阶函数为map()、reduce()、filter()、sorted()。

(1)map()高阶函数

map()函数将一个函数应用于一个或多个序列的每一个元素,并返回一个迭代器。

语法结构 :map(func,iterable)

功能:将iterable中的每一个元素自动传参给func函数,func会返回一个值,该值会称为iterator中的元素。

(2)reduce()高阶函数

reduce()函数会对参数序列中元素进行累积。

语法结构:reduce(func,sequence), func函数必须设置两个参数,设置1个返回值。

功能:将seq中的第0个和第1个元素传递给func...直到seq中的所有元素全部参与运算才会停止,最后得到一个结果。

(3)filter()高阶函数

filter()函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器。

语法结构:filter(func,iterable),返回值是一个iterator

功能:将iterable中的元素依次传递给func函数,如果func的返回值为True,则表示需要保留当前元素,如果func的返回值为False,则表示当前元素需要过滤掉。

(4)sorted()高阶函数

sorted()函数可以对可迭代对象进行排序。

语法结构:sorted(iterable,reverse,key=func),生成1个新的可迭代对象

功能:key参数允许你指定一个函数,该函数会在每个元素上调用,并使用其返回值进行排序。

三、装饰器

3.1 装饰器概念

在不修改原函数的基础上增加新的功能,这种在代码运行期间动态执行的机制被称为装饰器(Decorator),装饰器的作用为已经存在的函数或者类添加额外的功能,本质是内部函数访问外部函数中的变量。

3.2 装饰器语法

使用@xxx可以将一个装饰器作用于一个函数上,只需要将@xxx书写在一个函数的前面,则表示xxx装饰器装饰指定的函数。

python 复制代码
def outter(func):
	print('外部函数~~~~~~start')
	def inner():
  # 调用原函数
  		print('inner~~~~~~~~~~')
  		func()
  # 增加新的功能
  	print('new~~~~~~')
	print('外部函数~~~~~~end')
	return inner

@outter    # 等价于f = outter(a)。调用了外部函数
def a():
print('春节快乐')

print(a)   # <function outter.<locals>.inner at 0x000001AE54DCC430>
a()    # 等价于 f(),调用了内部函数

总结:

a.使用@xxx装饰某个函数,则该装饰器一定要先存在,然后才能使用

b.@xxx本质上表示调用装饰器的外部函数,自动将已知的函数传参给了func,同时自动将返回值inner接出来

c.当原函数传参给func之后,此时原函数的函数名就会给重新赋值,赋值为inner,所以a()表示调用的是inner()

四、包和模块

4.1 包和模块概念

模块Module:以.py为后缀的文件,称之为模块。

**包Package:**即文件夹,传统包里默认有一个__init__.py文件,可以为空文件,它是包的标志性文件,在需要情况下可以在里面进行一些包的初始化工作。

4.2 模块使用语法

方式一:import 模块名

方式二:from 模块名 import 变量名/函数名/类名

通过from xxx import xxx的方式导入,访问变量或调用函数的时候,可以直接书写变量名或函数名,当不同模块中出现了重名的变量或者函数,此时相互之间会影响,只能访问到后导入的内容。

4.3 默认模块

|----------|------------|----------------------------------------|
| 模块名 | 功能描述 | 主要类或函数 |
| time | 时间相关功能模块 | time():返回当前时间的时间戳 |
| time | 时间相关功能模块 | localtime():将时间戳转换为本地时间 |
| time | 时间相关功能模块 | gmtime():将时间戳转换为UTC时间 |
| time | 时间相关功能模块 | strftime():将struct_time对象格式化为字符串 |
| time | 时间相关功能模块 | strptime():将字符串解析为struct_time对象 |
| time | 时间相关功能模块 | sleep():使程序暂停指定的秒数 |
| datetime | 日期和时间的相关功能 | now():获取当前时间 |
| datetime | 日期和时间的相关功能 | datetime(year, month, day):创建指定日期时间的对象 |
| os | 文件目录操作管理功能 | os.listdir():列出目录下的所有文件和子目录 |
| os | 文件目录操作管理功能 | os.mkdir():创建新目录 |
| os | 文件目录操作管理功能 | os.rmdir():删除空目录 |
| os | 文件目录操作管理功能 | os.rename():重命名文件或目录 |
| os | 文件目录操作管理功能 | os.remove():删除文件 |
| os | 文件目录操作管理功能 | os.path.exists():检查路径是否存在。 |
| os | 文件目录操作管理功能 | os.path.isfile():检查路径是否是文件。 |
| os | 文件目录操作管理功能 | os.path.isdir():检查路径是否是目录。 |

五、面向对象

5.1 面向对象概述

面向对象是Python中的一种重要编程方式,它基于"对象"的概念来编写代码,使代码更加模块化、易于维护和易于扩展,有三大特征:封装、继承、多态。

5.2 类和对象概念

:是一个具有特殊功能的实体的集合或群体,用于创建具有相同属性和方法的对象。

对象:在一个类中,一个具有特殊功能的实体,能够帮忙解决特定的问题,对象是类的实例。通过类创建对象时,会调用类的构造函数(__init__方法)来初始化对象的属性。

类和对象两者之间的关系:类用于描述某一类对象的共同特征,而对象则是类的具体存在。

5.3 类和对象定义

类的语法结构:

class 类名():

类体

说明:(1)在同一个py文件中,可以定义多个类,但是如果要实现的需求较为复杂,一般会结合模块使用,在一个模块中定义一个类。

(2)定义类的过程中,类名后面的()可以省略,创建对象时的()不能省略。

(3)同一个类,默认情况下,可以创建无数个对象,每个对象都会被分配不同的地址。

(4)直接输出对象,默认的情况下,会得到一个地址。

5.4 对象创建
python 复制代码
m1 = MyClass1()
print(m1)
m2 = MyClass2()
print(m2,id(m2))
m22 = MyClass2()
print(m22,id(m22))
5.5 构造函数

构造函数是指创建对象时本身所运行的函数,Python使用__init__()函数作为对象的构造方法,当用户要在对象内指向对象本身时,可以使用self关键字,self代表对象本身。

python 复制代码
class Person():
def __init__(self,name,age):
  self.name = name
  self.age = age
def show(self):
  print(f'name:{self.name},age:{self.age}')
5.6 对象属性的动态绑定和限制绑定

(1)对象属性的动态绑定

只要是 对象.属性 = 值 类似这样的语法,都是给对象动态绑定属性,在默认情况下,对于属性的绑定没有任何限制。

(2)限制绑定

用__slots__限制对象属性的动态绑定,定义一个元组,将属性名以字符串的形式书写在元组中。

语法结构:slots = ('xx1','xx2','xx3')

python 复制代码
class Doctor():
# 用__slots__限制对象属性的动态绑定,定义一个元组,将属性名以字符串的形式书写在元组中,一般是结合实际需求或实际情况确定
__slots__ = ('name','age','kind')
# 注意:当元组中只有一个元素的时候,要添加逗号
# __slots__ =  ('name',)
def __init__(self,name,age):
  self.name = name
  self.age = age

doc = Doctor('张大夫',40)
doc.kind = '外科'
print(doc.name,doc.age,doc.kind)
# doc.a = 234   # AttributeError: 'Doctor' object has no attribute 'a'
# doc.eggw= 45
5.7 类中的属性

(1)定义位置不同

类属性:定义在类中

实例属性:动态绑定的属性(在__init__中或在类的外面直接动态绑定定义)

class MyClass():

hobby = 'study' # 类属性

def init(self,name):

self.name = name # 实例属性

num1.age = 18 # 实例属性

num = MyClass

(2)访问方式不同

类属性可以通过类名或对象访问

print(MyClass.hobby)

print(num.hobby)

实例属性只能通过对象访问

print(num.name)

(3)访问优先级不同

当类属性和实例属性重名时,通过对象访问,实例属性优先级最高。

(4)内存中的类属性和实例属性

类属性共享同一份地址,而实例属性为不同的地址。

(5)使用场景不同

类属性用于表示多个对象共享的数据,实例属性表示每个对象特有的数据。

5.8 类中的函数

类中的函数主要分为:实例函数、类函数、静态函数。

(1)实例函数

使用def关键字来定义一个方法,与一般函数定义不同,实例函数必须包self,self代表类的实例,语法结构如下:

def 实例函数名(self,参数)

函数体

return 返回值

语法说明:实例函数必须创建在类中,函数的第一个参数是self,代表对象本身, "return 返回值"可有可无,需要返回则用。

(2)类函数

类函数用@classmethod装饰器装饰,第一个形参是cls,cls是class的缩写,表示当前类,类函数之间相互调用,格式:cls.xxx()。语法结构如下:

@classmethod

def 函数名(cls):

函数体

return 返回值

(3)静态函数

静态函数用@staticmethod装饰器装饰,没有self函数,导致其无法访问类的实例属性;没有cls参数,导致无法访问类属性。

@staticmethod

def 函数名(cls):

函数体

return 返回值

实例函数、类函数、静态函数调用区别:实例函数只能通过对象调用,静态函数和类函数可以通过类名或对象调用。

5.9 面向对象的三大特征

面向对象的特征:封装、继承、多态。

(1) 封装

封装的本质:将类中的属性进行私有化,私有属性表示只能在当前类中被直接访问。

属性私有化示例:

python 复制代码
class Person():

    __slots__ = ("__name", "__age")   #限制动态绑定

    def __init__(self, name, age):

        # 私有属性,只需要在属性名的前面添加两个下划线__

        self.__name = name

        self.__age = age

    def show(self):

        print(f"姓名:{self.__name},年龄:{self.__age}")

# 创建对象,通过对象可以直接访问

p1 = Person("张三", 10)

# 通过对象无法直接访问

print(p1.__name,p1.__age) #报错:AttributeError: 'Person' object has no attribute 'name'

p1.show()    #输出  姓名:张三,年龄:10

# 获取值

    def func1(self):

        return self.__name

print(p1.func1()) #输出 张三

# 修改值

    def func2(self,a):

        self.__name = a

p1.func2('李四')

p1.show()    #输出  姓名:李四,年龄:10

(2)继承

继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的重用,一个子类可以继承多个父类。语法结构如下:

python 复制代码
class 子类类名(父类类名):

    类体

class 子类类名(父类类名1,父类类名2.......):

    类体

继承示例:

# 父类

class Person():  # 在此处的()中什么都不写,默认的父类仍然是object

    def __init__(self,name,age):

        self.name = name

        self.age = age

    def show(self):

        print('showing')

# 子类

class Doctor(Person):

    def __init__(self,name,age,kind):

        # 在子类的__init__中调用父类的__init__

        # 方式一:super(当前类,self).__init__(参数列表)

        # 方式二:super().__init__(参数列表)

        # 方式三:父类类名.__init__(self,参数列表)

         Person.__init__(self,name,age)

d = Doctor('王医生',22,'其他')

print(d.name,d.age)  # 输出 王医生 45

(3)多态

继承是多态的前提,体现方式分为:一种事物的多种体现形式,定义时并不确定是什么类型,要调用的是哪个方法,只有运行的时候才能确定调用的是哪个。

python 复制代码
class Animal():
def style(self):
  print('walking')
class Cat(Animal):
pass
class Dog(Animal):
pass
class Pig(Animal):
pass
class Bird(Animal):
def style(self):
  print('flying')
class Fish(Animal):
def style(self):
  print('swimming')
5.10 函数重写

重写(override):在继承的前提下,在子类中重新实现了父类中的函数功能。

重写函数注意事项:

1输出对象时会调用魔术函数__str__,该函数返回当前对象在计算机中的地址;

2当重写__str__时,返回值必须是一个字符串,一般是和当前对象相关的属性信息;

3当子类中重写了父类中的函数,创建子类对象调用函数,优先调用的是子类中的函数。

python 复制代码
class Person(object):
	def __init__(self,name,age):
  	self.name = name
  	self.age = age
	def show(self):
  	print(f'name:{self.name},age:{self.age}')
# 注意2:当重写__str__时,返回值必须是一个字符串,表示一个对象的字符串描述信息,一般是和当前对象相关的属性信息
	def __str__(self):
  # TypeError: __str__ returned non-string (type NoneType)
  	return f'name:{self.name},age:{self.age}'
5.11 运算符重载

运算符重载是指在类中定义特殊方法,使得该类的实例对象可以像内置类型一样进行运算,重写是指函数存在但是实现不同的需求,重载是指不支持指定的运算,通过重载让支持运算。

python 复制代码
class Person():
    def __init__(self,age):
        self.age = age
    def __gt__(self, other):
        return self.age > other.age

p1 = Person(10)
p2 = Person(23)
print(p1 > p2)
print(p1.__gt__(p2))
print(Person.__dict__)

5.12 对象的内置内容

内置对象:

slots:限制对象属性的动态绑定

dict:获取类或对象的所有信息【属性和函数】,返回一个字典

module;获取指定对象属于哪个模块,如果时当前模块,则结果为__main__,如果是其他模块,则结果为模块名

name:如果结果为__main__则说明运行的是当前文件,如果是模块名则表示运行的是其他文件

内置函数:

id():获取一个对象的内存地址

type():获取一个对象的数据类型

isinstance():判断一个对象的数据类型是否是指定类型

python 复制代码
lst = ['faf',24,6,False,34,True,'535',18]
l1 = [ele for ele in lst if isinstance(ele,int)]  # 涉及到继承,继承自int或int都会挑选
print(l1)  # [24, 6, False, 34, True, 18]
l2 = [ele for ele in lst if type(ele) == int]  # 精确匹配,只挑选int
print(l2)  # [24, 6, 34, 18]
相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书3 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小二·4 小时前
java基础面试题笔记(基础篇)
java·笔记·python
小喵要摸鱼6 小时前
Python 神经网络项目常用语法
python
一念之坤7 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
wxl7812278 小时前
如何使用本地大模型做数据分析
python·数据挖掘·数据分析·代码解释器
NoneCoder8 小时前
Python入门(12)--数据处理
开发语言·python
LKID体8 小时前
Python操作neo4j库py2neo使用(一)
python·oracle·neo4j
小尤笔记9 小时前
利用Python编写简单登录系统
开发语言·python·数据分析·python基础
FreedomLeo19 小时前
Python数据分析NumPy和pandas(四十、Python 中的建模库statsmodels 和 scikit-learn)
python·机器学习·数据分析·scikit-learn·statsmodels·numpy和pandas