Python函数对象,Python 面向对象
本文主要详细介绍python的功能和面向对象。本文中的示例代码非常详细,具有一定的参考价值。感兴趣的朋友可以参考一下,希望能帮到你。
00-1010函数、参数、变量、作用域、嵌入式函数和闭包lambda表达式、面向对象三大特征类、类对象和实例、对象类属性和对象属性私有魔术方法基本魔术方法算术运算符属性访问描述符迭代器和生成器迭代器生成器摘要
目录
在python中一切都是对象,函数也不例外。
在C或Java中,你可以发现函数的返回值要么是空的,要么是某种数据类型,但在python中,返回值可以是任何对象,包括函数.
函数
函数的参数有很多种,主要是3360。
1.位置自变量):)是最常见的x,y等。
2默认参数):)给定一个默认值,用户也可以传入一个参数来调整。
定义函数(x,y=3):
打印(x y)
函数(1) # 4
func(1,666) # 667
3.变量argument):)不限制输入参数的个数,传入后自动保存为元组类型。
1.*args是一个可变参数,args接收一个元组
def printinfo(arg1,*args):
打印(arg1)
print(args,type(args))
Printinfo(10) #只有一个参数,没有任何属于args的东西。
# 10
#()类“元组”
Printinfo(70,60,50) #除了arg1位置匹配的,其他都传入变量参数。
# 70
# (60,50)类“元组”
4.关键字自变量):)不限制关键字的数量和命名,输入后自动保存为字典。
1.**kw是一个关键字参数,kw接收一个dict。
def printinfo(arg1,*args):
打印(arg1)
print(args,type(args))
Printinfo(10) #只有一个参数,没有任何属于args的东西。
# 10
#()类“元组”
Printinfo(70,60,50) #除了arg1位置匹配的,其他都传入变量参数。
# 70
# (60,50)类“元组”
5.命名关键字参数(名称关键字参数)
1.关键字参数的命名是为了限制调用者可以传入的“参数名”,或者提供默认值.
style="margin-left:40px">2.与关键字参数不同的是, 关键字参数的名字和值都是任意的, 后续再进行匹配使用, 而命名关键字则只能接受给定的关键字作为参数.定义命名关键字参数
3.不要忘了写分隔符*
, 否则定义的是位置参数, 命名关键字参数调用函数时必须给定参数名.
def person(name, *, age, height=1.90):print(f{name}今年{age}岁, 身高{height:.2f}m)
person(张三, age=18, height=1.80) # 张三今年18岁, 身高1.80m
person(李四, age=18) # 李四今年18岁, 身高1.90m
person(王五) # TypeError, 需要传入给定关键字
6.参数组合
在Python
中定义函数时, 以上这5种参数都可以使用, d但最多可以使用4种, 并且要注意顺序:
1.位置参数、默认参数、可变参数和关键字参数.
2.位置参数、默认参数、命名关键字参数和关键字参数.
变量作用域
在python程序中, 处于不同位置的变量, 有不同的作用域.
- 定义在函数内部的变量拥有局部作用域, 该变量称为局部变量.
- 定义在函数外部的变量拥有全局作用域, 该变量称为全局变量.
- 局部变量只能在其被声明的函数内部访问, 而全局变量可以在整个程序范围内访问.
需要注意的是:
- 当局部变量试图访问全局变量时, 一定要在函数内声明
global
. - 当局部变量与全局变量命名冲突时, 程序会优先选择局部变量.
内嵌函数和闭包
内嵌函数就是在外层函数内定义内层函数.
def outer():print(outer函数在这被调用)
def inner():
print(inner函数在这被调用)
inner() # 该函数只能在outer函数内部被调用
outer()
# outer函数在这被调用
# inner函数在这被调用
闭包是一个比较重要的语法结构, 结构上与内嵌函数类似, 区别在于返回值, 闭包的外层函数返回值是一个函数.
如果在一个内部函数里对外层非全局作用域的变量进行引用, 那么内部函数就被认为是闭包.
通过闭包可以访问外层非全局作用域的变量, 这个作用域称为闭包作用域.
def funX(x):def funY(y):
print(使用funY(y))
return x * y
return funY
i = funX(8)
print(type(i)) # <class function>
print(i(5)) # 40
注意到上述代码中, 内部函数FunY
中使用了外部非全局作用域的变量x
.
同样是, 函数内嵌套的函数作用域也需要特别注意, 若我们需要修改闭包内的变量, 需要使用nonlocal
关键字.
num = 999def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(finner中num = {num})
inner()
print(fouter中num = {num})
outer()
# inner中num = 100
# outer中num = 100
print(f全局中num = {num})
# 全局中num = 999
lambda 表达式
lambda需要注意的是:
- 匿名函数没有
return
, 表达式本身就是返回值. - 匿名函数拥有『自己的命名空间』, 不能访问参数列表之外或全局变量.
匿名函数主要适用于函数式编程(函数不会影响函数之外的内容)的一些高阶函数中. 例如map映射和filter过滤, 当然也可以在自己自定义函数中使用.
odd = lambda x: x % 2 == 1templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(templist)) # [1, 3, 5, 7, 9]
m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(list(m1)) # [1, 4, 9, 16, 25]
面向对象
三大特性
面向对象就必须了解三大特性:
- 封装: 把客观事物封装成抽象的类, 让数据和方法给信任的类或对象操作, 而隐藏部分信息.
- 继承: 子类自动共享父类的属性和方法.
- 一般认为一个类是自身的子类;
- 可以使用
issubclass(B, A)
查看B
是否是A
的子类. - python也支持多继承, 但会使得类的整体层次复杂, 所以并不建议使用.
- 多态: 同一个方法的调用, 会由于不同对象而得到不同的结果.
- 必要条件是
继承
和方法的重写
.
- 必要条件是
类、类对象 和 实例对象
- 类: 就是指对类的定义
- 类对象: 是在创建类的时候, 在内存开辟的一个空间, 一个类只有一个类对象.
- 实例对象: 通过实例化类创建的对象, 可以有多个.
类属性 和 对象属性
- 类属性: 类定义内, 类方法外定义的变量称为类属性, 类属性属于类对象, 可以被多个实例化对象所共享, 就像
我们都有一个家, 名字叫中国
一样. - 对象属性: 对象属性和具体创建的对象实例直接相关, 并且相互之间不共享属性, 就像
我的老婆只是我的
一样.
class A():a = 0 #类属性
def __init__(self, xx):
A.a = xx #使用类属性可以通过 (类名.类属性)调用。
有一些操作属性的方法:
- 使用
hasattr(object, name)
来判断对象是否包含对应的属性或方法. - 使用
getattr(object, name)
来获取属性或方法. - 使用
setattr(object, name, value)
来修改属性值, 或创建新的属性和值. - 使用
delattr(object, name)
来删除属性.
class A(object):name = 张三
def set(self, a, b):
x = a
a = b
b = x
print(a, b)
a = A()
print(hasattr(a, name)) # 判断是否有name属性 True
print(hasattr(a, set)) # 判断是否有set方法 True
x = getattr(a, name) # 获取属性值
print(x) # 张三
c = getattr(a, set) # 获取方法
c(a=1, b=2) # 2 1
私有
私有属性和方法仅需在定义命名的时候加上两个下划线"__
"即可.
相对于公有属性和公有方法来说, 私有属性和私有方法更加的安全. 从定义上来说, 将需要安全保护的属性和方法封装为私有, 可以阻止外部直接调用, 而必须使用实例化对象方法
或类方法
进行调用, 从而提高安全性.
但在python中的私有是『伪私有』, 即可以使用类名, 通过object._className__attrName
访问私有属性,用object._className__func()
访问私有方法.
class JustCounter:__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
print(counter.publicCount) # 1
# 特殊方法依旧可以访问
print(counter._JustCounter__secretCount) # 1
# 直接访问则会报错.
print(counter.__secretCount)
实例直接使用点就可以增加属性了, 这点需要注意一下.
class B:def func(self):
print(调用func方法)
b = B()
print(b.__dict__) # 查看属性 {}
b.name = 张三
b.age = 18
print(b.__dict__) # 查看属性{name: 张三, age: 18}
b1 = B()
print(b1.__dict__) # 查看属性 {}
魔法方法
基本的魔法方法
魔法方法基本上是被下划线包围的一些特殊方法. 相比于普通的方法, 它能够在适当的时候自动调用. 第一个参数一般是cls
『类方法』或者self
『实例方法』.
__init__(self[, ...])
构造器, 当一个实例被创建的时候调用的初始化方法.__new__(cls[, ...])
在一个对象实例化的时候所调用的第一个方法, 在调用__init__
初始化前, 先调用__new__
.- 需要注意的是,
__new__
的返回值必须为当前类的实例, 否则将不会调用__init__
初始化. - 主要是在继承一些不可变的class(比如
int, str, tuple
)时, 提供一个自定义该类实例化过程的途径.
- 需要注意的是,
__del__(self)
析构器, 当一个对象将要被系统回收之时调用的方法.__str__(self)
: 当你打印一个对象、使用%s
格式化或使用str
强转数据类型的时候,触发__str__
.__repr__(self)
是__str__(self)
的备胎, 情况类似, 不过自定义时往往更加准确, 主要用于调试.
算术运算符
普通的计算在对象中是无法进行的, 需要自定义计算方式.
__add__(self, other)
定义加法的行为:+
__sub__(self, other)
定义减法的行为:-
__mul__(self, other)
定义乘法的行为:*
__truediv__(self, other)
定义真除法的行为:/
__floordiv__(self, other)
定义整数除法的行为://
__mod__(self, other)
定义取模算法的行为:%
__divmod__(self, other)
定义当被divmod()
调用时的行为
divmod(a, b)
把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
。
__pow__(self, other[, module])
定义当被power()
调用或**
运算时的行为
__lshift__(self, other)
定义按位左移位的行为:<<
__rshift__(self, other)
定义按位右移位的行为:>>
__and__(self, other)
定义按位与操作的行为:&
__xor__(self, other)
定义按位异或操作的行为:^
__or__(self, other)
定义按位或操作的行为:
还有对应的反运算符, 在之前加上r
即可, 例如__rsub__
. 对应增量赋值运算符, 在之前加上i
即可, 例如__isub__
.
属性访问
__getattr__(self, name)
: 定义当用户试图获取一个不存在的属性时的行为.
__getattribute__(self, name)
: 定义当该类的属性被访问时的行为(先调用该方法, 查看是否存在该属性, 若不存在, 接着去调用__getattr__
).
__setattr__(self, name, value)
: 定义当一个属性被设置时的行为.
__delattr__(self, name)
: 定义当一个属性被删除时的行为.
描述符
描述符就是将某种特殊类型的类的实例指派给另一个类的属性.
__get__(self, instance, owner)
: 用于访问属性, 它返回属性的值.
__set__(self, instance, value)
: 将在属性分配操作中调用, 不返回任何内容.
__del__(self, instance)
: 控制删除操作, 不返回任何内容.
迭代器和生成器
迭代器
迭代是Python
最强大的功能之一, 是访问集合元素的一种方式.
- 迭代器是一个可以记住遍历的位置的对象.
- 迭代器对象从集合的第一个元素开始访问, 直到所有的元素被访问完结束.
- 迭代器只能往前不会后退.
- 字符串, 列表或元组对象都可用于创建迭代器.
迭代器有两个基本的方法:iter()
和next()
:
iter(object)
函数用来生成迭代器.next(iterator[, default])
返回迭代器的下一个项目. 在元素为空时返回默认值, 若没有则会触发StopIteration
异常. 在元组推导式和next中使用过, 不过是下面的『生成器』.
把一个类作为一个迭代器使用需要在类中实现两个魔法方法__iter__()
与__next__()
.
__iter__(self)
定义当迭代容器中的元素的行为, 返回一个特殊的迭代器对象, 这个迭代器对象实现了__next__()
方法并通过StopIteration
异常标识迭代的完成.__next__()
返回下一个迭代器对象.StopIteration
异常用于标识迭代的完成,防止出现无限循环的情况,在__next__()
方法中我们可以设置在完成指定循环次数后触发StopIteration
异常来结束迭代。
class Fibs:def __init__(self, n=10):
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > self.n:
raise StopIteration
return self.a
fibs = Fibs(100)
for each in fibs:
print(each, end= )
# 1 1 2 3 5 8 13 21 34 55 89
生成器
在 Python 中,使用了yield
的函数被称为生成器(generator)。
- 跟普通函数不同的是, 生成器是一个返回迭代器的函数, 只能用于迭代操作, 更简单点理解生成器就是一个迭代器.
- 在调用生成器运行的过程中, 每次遇到
yield
时函数会暂停并保存当前所有的运行信息, 返回yield
的值, 并在下一次执行next()
方法时从当前位置继续运行. - 调用一个生成器函数, 返回的是一个迭代器对象.
def libs(n):a = 0
b = 1
while True:
a, b = b, a + b
if a > n:
return
yield a
for each in libs(100):
print(each, end= )
# 1 1 2 3 5 8 13 21 34 55 89
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注盛行IT软件开发工作室的更多内容!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。