函数
1.函数定义
- Python将函数也视作对象,可以从另一个函数中返回出来去构建高阶函数,比如:参数是函数,返回值也是函数
- 函数以def关键词开头,后接函数名和圆括号()
- return 表示结束函数,选择性地返回一个值给调用方,不带表达式的return相当于返回None
2.函数调用
def printme(str):
print(str)
printme("我要调用用户自定义函数")
printme("再次调用同一函数")
temp = printme('hello')
print(temp)
我要调用用户自定义函数
再次调用同一函数
hello
None
3.函数文档
def MyFirstFunction(name):
"函数定义过程中name是形参"
print("传递进来的{0}叫做实参,因为Ta是具体的参数值".format(name))
MyFirstFunction('老马的程序人生')
print(MyFirstFunction.__doc__)
help(MyFirstFunction)
传递进来的老马的程序人生叫做实参,因为Ta是具体的参数值
函数定义过程中name是形参
Help on function MyFirstFunction in module __main__:
MyFirstFunction(name)
函数定义过程中name是形参
4.函数参数
Python的函数具有非常灵活多样的参数形态,从简到繁的参数形态如下:
- 位置参数
- 默认参数
- 可变参数
- 关键字参数
- 命名关键字参数
- 参数组合
4.1 位置参数
def functionname(arg1):
"函数,文档字符串"
return [expression]
- arg1 - 位置参数,这些参数在调用函数时位置要固定
4.2 默认参数
def functionname(arg1,arg2 = v):
"函数 文档字符串"
return [expression]
- arg2 = v - 默认参数=默认值,调用函数时,默认参数没有传入则为默认值
- 默认参数一定要放在位置参数后面
def printinfo(name,age = 0):
print("Name:{0},Age:{1}".format(name,age))
printinfo("小马")
printinfo("小马",10)
Name:小马,Age:0
Name:小马,Age:10
- Python允许函数调用时参数的顺序与声明时不一致,因为Python解释器能够用参数名匹配参数值
def printinfo(name,age = 0):
print("Name:{0},Age:{1}".format(name,age))
printinfo(age = 0,name = "小马")
Name:小马,Age:0
4.3 可变参数
def functionname(arg1,arg2 = v,*args):
return [expression]
- *args -可变参数,可以是从零个到任意个,自动组装成元组
- 加了星号(*)的变量名会存放所有未命名的变量参数
def printinfo(arg1,*args):
print(arg1)
for var in args:
print(var)
printinfo(10)
printinfo(70,60,50)
10
70
60
50
4.4 关键字参数
def functionname(arg1,arg2 = v,args,*kw):
return [expression]
- *kw -关键字参数,可以是从零个到任意个,自动组装成字典
def printinfo(arg1,*args,**kwargs):
print(arg1)
print(args)
print(kwargs)
printinfo(70,60,50)
printinfo(70,60,50,a = 1,b =2)
70
(60, 50)
{}
70
(60, 50)
{'a': 1, 'b': 2}
- 可变参数和关键字参数的同异总结如下:
- 可变参数允许传入零个到任意个参数,他们在函数调用时会自动组装成一个元组
- 关键字参数允许传入零个到任意个参数,他们在函数内部自动组装成一个字典。
4.5 命名关键字参数
def functionname(arg1,arg2 = v,args,* ,nkw,** kwargs):
return [expression]
*
,nkw - 命名关键字参数,用户想要输入的关键字参数,定义方式是在nkw前面加个分隔符 *- 如果想要限制关键字参数的名字,可以使用命名关键字参数
- 使用命名关键字参数时,要特别注意不能缺少参数名。
def printinfo(arg1,*,nkw,**kwargs):
print(arg1)
print(nkw)
print(kwargs)
printinfo(70,nkw = 10,a=1,b =2)
printinfo(70,10,a=1,b=2)
70
10
{'a': 1, 'b': 2}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-670826578daa> in <module>
5
6 printinfo(70,nkw = 10,a=1,b =2)
----> 7 printinfo(70,10,a=1,b=2)
TypeError: printinfo() takes 1 positional argument but 2 were given
4.6 参数组合
参数定义的顺序:
- 位置参数、默认参数、可变参数和关键字参数
- 位置参数、默认参数、命名关键字参数和关键字参数
注意定义可变参数和关键字参数的语法:
*args
是可变参数,args接收的是一个tuple**kw
是关键字参数,kw接收的是一个dict
5. 函数的返回值
def add(a,b):
return a+b
print(add(1,2))
print(add([1,2,3],[4,5,6]))
3
[1, 2, 3, 4, 5, 6]
def back():
return [1,'小马的程序人生',3.14]
print(back())
[1, '小马的程序人生', 3.14]
def back():
return 1,'小马的程序人生',3.14
print(back())
(1, '小马的程序人生', 3.14)
def printme(str):
print(str)
temp = printme('hello')
print(temp)
print(type(temp))
hello
None
<class 'NoneType'>
6.变量作用域
- Python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量在哪里赋值的。
- 定义在函数内部的变量拥有局部作用域,该变量称为局部变量
- 定义在函数外部的变量拥有全局作用域,该变量称为全局变量
- 局部变量只能在其声明的函数内部访问,而全局变量可以在整个程序范围内访问。
def discount(price,rate):
final_price = price * rate
return final_price
old_price = float(input("请输入原价:"))
rate = float(input("请输入折扣率:"))
new_price = discount(old_price,rate)
print("打折后价格是:%.2f"%new_price)
请输入原价:98
请输入折扣率:0.9
打折后价格是:88.20
- 当内部作用域想修改外部作用域变量时,需要用到global和nonlocal关键字
num = 1
def fun1():
global num
print(num)
num = 123
print(num)
fun1()
print(num)
1
123
123
7.1 内嵌函数
def outer():
print("outer函数在这被调用")
def inner():
print('inner函数在这里被调用')
inner()
outer()
outer函数在这被调用
inner函数在这里被调用
7.1.1 闭包
- 是函数式编程的一个重要的语法结构,是一种特殊的内嵌函数
- 如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包
- 通过闭包可以访问外层非全局作用域的变量,这个作用域称为
闭包作用域
def funX(x):
def funY(y):
return x*y
return funY
i = funX(8)
print(type(i))
print(i(5))
<class 'function'>
40
#闭包的返回值通常是函数
def make_counter(init):
counter = [init]
def inc():counter[0] += 1
def dec():counter[0] -= 1
def get():return counter[0]
def reset(): counter[0] = init
return inc,dec,get,reset
inc,dec,get,reset = make_counter(0)
inc()
inc()
inc()
print(get())
dec()
print(get())
reset()
print(get())
3
2
0
#修改闭包作用域中的变量则需要`nonlocal`关键字
def outer():
num = 10
def inner():
nonlocal num
num = 100
print(num)
inner()
print(num)
outer()
100
100
7.1.2 递归
- 如果一个函数在内部调用自身本身,这个函数就是递归函数
n = 5
for k in range(1,5):
n = n * k
print(n)
def factorial(n):
if n ==1:
return 1
return n*factorial(n-1)
print(factorial(5))
120
120
#斐波拉契数列
i = 0
j = 1
lst = list([i,j])
for k in range(2,11):
k = i+j
lst.append(k)
i = j
j = k
print(lst)
def recur_fibo(n):
if n<=1:
return n
return recur_fibo(n-1) + recur_fibo(n-2)
lst = list()
for k in range(11):
lst.append(recur_fibo(k))
print(lst)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
#设置递归的层数,python默认递归层数为100
import sys
sys.setrecursionlimit(1000)
Lambda表达式
匿名函数的定义
在Python里有两类函数:
- 第一类:用def关键词定义的正规函数
- 第二类:用lambda关键词定义的匿名函数
Python使用lambda
关键词来创建匿名函数,语法结构为:
lambda argument_list:expression
- lambda - 定义匿名函数的关键词
- argument_list - 函数参数,它们可以是位置参数,默认参数,关键字参数和正规函数里的参数类型一样
- expression-表达式,输入函数参数,输出一些值
注:
- expreion中没有return语句,因为lambda不需要它来返回,表达式本身结果就是返回值
- 匿名函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间的参数
def sqr(x):
return x ** 2
print(sqr)
# <function sqr at 0x000000BABD3A4400>
y = [sqr(x) for x in range(10)]
print(y)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
lbd_sqr = lambda x: x ** 2
print(lbd_sqr)
# <function <lambda> at 0x000000BABB6AC1E0>
y = [lbd_sqr(x) for x in range(10)]
print(y)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
sumary = lambda arg1, arg2: arg1 + arg2
print(sumary(10, 20)) # 30
func = lambda *args: sum(args)
print(func(1, 2, 3, 4, 5)) # 15
<function sqr at 0x000002DDE39820D0>
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<function <lambda> at 0x000002DDE551C0D0>
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
30
15
匿名函数的应用
函数式编程是指代码中每一块都是不可变的,都由纯函数形式组成。这里的纯函数指的是函数本身相互独立,互不影响,对于相同的输入,总会由相同的输出,没有任何副作用。
# 非函数式编程
def f(x):
for i in range(0,len(x)):
x[i] += 10
return x
x = [1,2,3]
f(x)
print(x)
[11, 12, 13]
#函数式编程
def f(x):
x = []
for item in x:
y.append(item+10)
return y
x = [1,2,3]
f(x)
print(x)
[1, 2, 3]
匿名函数常常应用与函数式编程的高阶函数,主要有两种形式:
- 参数是函数
- 返回值是函数
比如,在filter
和map
函数中的应用:
- filter(function,iterable)过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用list()来转换
odd = lambda x:x%2 ==1
templist = filter(odd,[1,2,3,4,5,6,7,8,9])
print(list(templist))
[1, 3, 5, 7, 9]
- map(function,*iterables) 根据提供的函数对指定序列做映射
m1 = map(lambda x:x **2,[1,2,3,4,5])
print(list(m1))
m2 = map(lambda x,y:x+y,[1,3,5,7,9],[2,4,6,8,10])
print(list(m2))
[1, 4, 9, 16, 25]
[3, 7, 11, 15, 19]
- 自定义高阶函数
def apply_to_list(fun,some_list):
return fun(some_list)
lst = [1,2,3,4,5]
print(apply_to_list(sum,lst))
print(apply_to_list(len,lst))
print(apply_to_list(lambda x:sum(x)/len(x),lst))
15
5
3.0
类与对象
对象 = 属性+方法
对象是类的实例,类主要定义对象的结构,然后我们以类为模板创建对象。类不但包括方法定义,而且还包括所有实例共享的数据。
- 封装:信息隐藏技术
可以使用关键字class
定义python类,关键字后面紧跟类的名称、分号和类的实现。
class Turtle: #Python中的类名约定以大写字母开头
#属性
color = 'green'
weight = 10
legs = 4
shell = True
mouth = '大嘴'
#方法
def climb(self):
print("我正在很努力的向前爬...")
def run(self):
print("我正在飞快地向前跑...")
def bite(self):
print('咬死你咬死你!!')
def eat(self):
print('有得吃,真满足...')
def sleep(self):
print('困了,睡了,晚安,zzz')
tt = Turtle()
print(tt)
print(type(tt))
print(tt.__class__)
print(tt.__class__.__name__)
tt.climb()
tt.run()
tt.bite()
print(type(Turtle))
<__main__.Turtle object at 0x000002DDE4F5D2E0>
<class '__main__.Turtle'>
<class '__main__.Turtle'>
Turtle
我正在很努力的向前爬...
我正在飞快地向前跑...
咬死你咬死你!!
<class 'type'>
- 继承:子类自动共享父类之间数据和方法地机制
class MyList(list):
pass
lst = MyList([1,5,2,7,8])
lst.append(9)
lst.sort()
print(lst)
[1, 2, 5, 7, 8, 9]
- 多态:不同对象对同一方法响应不同地行动
class Animal:
def run(self):
raise AttributeError('子类必须实现这个方法')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
def func(animal):
animal.run()
func(Pig())
# pig is walking
pig is walking
self是什么?
Python 的self
相当于C++的this
指针
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
<__main__.Test object at 0x000002DDE50AC2B0>
<class '__main__.Test'>
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称self
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...
我叫球A,该死的,谁踢我...
我叫球B,该死的,谁踢我...
Python的魔法方法
类有一个名为__init__(self,param1,...,paramn)
的魔法方法,该方法在类实例化时会自动调用
class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball("球A")
b = Ball("球B")
c = Ball("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...
我叫球A,该死的,谁踢我...
我叫球B,该死的,谁踢我...
公有和私有
在Python中定义私有变量只需要在变量名或函数名前加上__
两个下划线,那么这个函数或变量就会变为私有了
- 类的私有属性实例
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
# Python的私有为伪私有
print(counter._JustCounter__secretCount) # 2
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
1
2
2
2
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-20-0e7487766f54> in <module>
16 # Python的私有为伪私有
17 print(counter._JustCounter__secretCount) # 2
---> 18 print(counter.__secretCount)
19 # AttributeError: 'JustCounter' object has no attribute '__secretCount'
AttributeError: 'JustCounter' object has no attribute '__secretCount'
- 类的私有方法实例
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name : 老马的程序人生
# url : https://blog.csdn.net/LSGO_MYP
x.foo()
# 这是公共方法
# 这是私有方法
x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'
name : 老马的程序人生
url : https://blog.csdn.net/LSGO_MYP
这是公共方法
这是私有方法
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-21-555cf676b575> in <module>
25 # 这是私有方法
26
---> 27 x.__foo()
28 # AttributeError: 'Site' object has no attribute '__foo'
AttributeError: 'Site' object has no attribute '__foo'
继承
- 如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性
# 类定义
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" % (self.name, self.age))
# 单继承示例
class student(people):
grade = ''
def __init__(self, n, a, w, g):
# 调用父类的构函
people.__init__(self, n, a, w)
self.grade = g
# 覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
s = student('小马的程序人生', 10, 60, 3)
s.speak()
# 小马的程序人生 说: 我 10 岁了,我在读 3 年级
小马的程序人生 说: 我 10 岁了,我在读 3 年级
注意:如果上面的程序去掉:people.__init__(self, n, a, w)
,则输出:说: 我 0 岁了,我在读 3 年级,因为子类的构造方法把父类的构造方法覆盖了。
import random
class Fish:
def __init__(self):
self.x = random.randint(0, 10)
self.y = random.randint(0, 10)
def move(self):
self.x -= 1
print("我的位置", self.x, self.y)
class GoldFish(Fish): # 金鱼
pass
class Carp(Fish): # 鲤鱼
pass
class Salmon(Fish): # 三文鱼
pass
class Shark(Fish): # 鲨鱼
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("吃货的梦想就是天天有得吃!")
self.hungry = False
else:
print("太撑了,吃不下了!")
self.hungry = True
g = GoldFish()
g.move() # 我的位置 9 4
s = Shark()
s.eat() # 吃货的梦想就是天天有得吃!
s.move()
# AttributeError: 'Shark' object has no attribute 'x'
我的位置 2 1
吃货的梦想就是天天有得吃!
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-3-f795a471252a> in <module>
40 s = Shark()
41 s.eat() # 吃货的梦想就是天天有得吃!
---> 42 s.move()
43 # AttributeError: 'Shark' object has no attribute 'x'
<ipython-input-3-f795a471252a> in move(self)
7
8 def move(self):
----> 9 self.x -= 1
10 print("我的位置", self.x, self.y)
11
AttributeError: 'Shark' object has no attribute 'x'
出现上述报错的原因是因为子类的构造方法覆盖了父类的构造方法,导致父类构造方法中的变量无法继承,有以下两种解决方法。
- 调用未绑定的父类方法
class Shark(Fish): # 鲨鱼
def __init__(self):
Fish.__init__(self)
self.hungry = True
def eat(self):
if self.hungry:
print("吃货的梦想就是天天有得吃!")
self.hungry = False
else:
print("太撑了,吃不下了!")
self.hungry = True
- 使用super函数
super().__init__()
class Shark(Fish): # 鲨鱼
def __init__(self):
super().__init__()
self.hungry = True
def eat(self):
if self.hungry:
print("吃货的梦想就是天天有得吃!")
self.hungry = False
else:
print("太撑了,吃不下了!")
self.hungry = True
组合
class Turtle:
def __init__(self, x):
self.num = x
class Fish:
def __init__(self, x):
self.num = x
class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x)
self.fish = Fish(y)
def print_num(self):
print("水池里面有乌龟%s只,小鱼%s条" % (self.turtle.num, self.fish.num))
p = Pool(2, 3)
p.print_num()
# 水池里面有乌龟2只,小鱼3条
水池里面有乌龟2只,小鱼3条
类、类对象和实例对象
类对象:创建一个类,表示一个对象在内存开辟了一块空间,称为类对象,类对象只有一个。
实例对象:通过实例化类创建的对象,称为实例对象,实例对象有多个。
class A(object):
pass
# 实例化对象 a、b、c都属于实例对象。
a = A()
b = A()
c = A()
类属性:类里面方法外定义的变量称为类属性,类属性所属于类对象并且多个实例对象之间共享同一个类属性,类属性所有通过该类实例化的对象都能共享
class A():
a = 0 #类属性
def __init__(self, xx):
A.a = xx #使用类属性可以通过 (类名.类属性)调用。
实例属性:实例属性和具体的某个实例对象有关系,并且一个实例对象和另外一个实例对象是不共享属性的,说白了实例属性只能在自己的对象里面使用,其他的对象不能直接使用,因为self是谁调用,它的值就属于该对象。
# 创建类对象
class Test(object):
class_attr = 100 # 类属性
def __init__(self):
self.sl_attr = 100 # 实例属性
def func(self):
print('类对象.类属性的值:', Test.class_attr) # 调用类属性
print('self.类属性的值', self.class_attr) # 相当于把类属性 变成实例属性
print('self.实例属性的值', self.sl_attr) # 调用实例属性
a = Test()
a.func()
# 类对象.类属性的值: 100
# self.类属性的值 100
# self.实例属性的值 100
b = Test()
b.func()
# 类对象.类属性的值: 100
# self.类属性的值 100
# self.实例属性的值 100
a.class_attr = 200
a.sl_attr = 200
a.func()
# 类对象.类属性的值: 100
# self.类属性的值 200
# self.实例属性的值 200
b.func()
# 类对象.类属性的值: 100
# self.类属性的值 100
# self.实例属性的值 100
Test.class_attr = 300
a.func()
# 类对象.类属性的值: 300
# self.类属性的值 200
# self.实例属性的值 200
b.func()
# 类对象.类属性的值: 300
# self.类属性的值 300
# self.实例属性的值 100
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100
类对象.类属性的值: 100
self.类属性的值 200
self.实例属性的值 200
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100
类对象.类属性的值: 300
self.类属性的值 200
self.实例属性的值 200
类对象.类属性的值: 300
self.类属性的值 300
self.实例属性的值 100
绑定
Python 对象的数据属性通常存储在名为.__ dict__
的字典中,我们可以直接访问__dict__
,或利用 Python 的内置函数vars()
获取.__ dict__
。
class CC:
def setXY(self, x, y):
self.x = x
self.y = y
def printXY(self):
print(self.x, self.y)
dd = CC()
print(dd.__dict__)
# {}
print(vars(dd))
# {}
print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000C3473DA048>, 'printXY': <function CC.printXY at 0x000000C3473C4F28>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
dd.setXY(4, 5)
print(dd.__dict__)
# {'x': 4, 'y': 5}
print(vars(CC))
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
{}
{}
{'__module__': '__main__', 'setXY': <function CC.setXY at 0x000001F1E5F4DC10>, 'printXY': <function CC.printXY at 0x000001F1E5F4DB80>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
{'x': 4, 'y': 5}
{'__module__': '__main__', 'setXY': <function CC.setXY at 0x000001F1E5F4DC10>, 'printXY': <function CC.printXY at 0x000001F1E5F4DB80>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
{'__module__': '__main__', 'setXY': <function CC.setXY at 0x000001F1E5F4DC10>, 'printXY': <function CC.printXY at 0x000001F1E5F4DB80>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
一些相关的内置函数
- issubclass(class,classinfo)方法用于判断参数class是否是类型参数classsinfo的子类
- 一个类被认为是其自身的子类
- classinfo可以是类对象的元组,只要class是其中任意一个候选类的子类则返回True
class A:
pass
class B(A):
pass
print(issubclass(B, A)) # True
print(issubclass(B, B)) # True
print(issubclass(A, B)) # False
print(issubclass(B, object)) # True
True
True
False
True
- isinstance(object,classinfo)方法用于判断一个对象是否是一个已知的类型,类似type()
- type()不会认为子类是一种父类类型,不考虑继承关系
- isinstance()会认为子类是一种父类类型,考虑继承关系
- 如果第一个参数不是对象,则永远返回False
- 如果第二个参数不是类或者由类对象组成的元组,则会抛出异常
a = 2
print(isinstance(a, int)) # True
print(isinstance(a, str)) # False
print(isinstance(a, (str, int, list))) # True
class A:
pass
class B(A):
pass
print(isinstance(A(), A)) # True
print(type(A()) == A) # True
print(isinstance(B(), A)) # True
print(type(B()) == A) # False
True
False
True
True
True
True
False
- hasattr(object,name)用于判断对象是否包含对应的属性
class Coordinate:
x = 10
y = -5
z = 0
point1 = Coordinate()
print(hasattr(point1, 'x')) # True
print(hasattr(point1, 'y')) # True
print(hasattr(point1, 'z')) # True
print(hasattr(point1, 'no')) # False
True
True
True
False
- getattr(object,name,default)用于返回一个对象属性值
class A(object):
bar = 1
a = A()
print(getattr(a, 'bar')) # 1
print(getattr(a, 'bar2', 3)) # 3
print(getattr(a, 'bar2'))
# AttributeError: 'A' object has no attribute 'bar2'
1
3
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-14-a381bb20461b> in <module>
6 print(getattr(a, 'bar')) # 1
7 print(getattr(a, 'bar2', 3)) # 3
----> 8 print(getattr(a, 'bar2'))
9 # AttributeError: 'A' object has no attribute 'bar2'
AttributeError: 'A' object has no attribute 'bar2'
- setattr(object,name,value)对应函数getattr(),用于设置属性值,该属性不一定是存在的
class A(object):
bar = 1
a = A()
print(getattr(a, 'bar')) # 1
setattr(a, 'bar', 5)
print(a.bar) # 5
setattr(a, "age", 28)
print(a.age) # 28
1
5
28
- delattr(object,name)用于删除属性
class Coordinate:
x = 10
y = -5
z = 0
point1 = Coordinate()
print('x = ', point1.x) # x = 10
print('y = ', point1.y) # y = -5
print('z = ', point1.z) # z = 0
delattr(Coordinate, 'z')
print('--删除 z 属性后--') # --删除 z 属性后--
print('x = ', point1.x) # x = 10
print('y = ', point1.y) # y = -5
# 触发错误
print('z = ', point1.z)
# AttributeError: 'Coordinate' object has no attribute 'z'
x = 10
y = -5
z = 0
--删除 z 属性后--
x = 10
y = -5
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-e10298e6b2b2> in <module>
18
19 # 触发错误
---> 20 print('z = ', point1.z)
21 # AttributeError: 'Coordinate' object has no attribute 'z'
AttributeError: 'Coordinate' object has no attribute 'z'
魔法方法
- 魔法方法总是被双下划线包围
- 魔法方法是面向对象Python的一切
- 魔法方法总能在适当的时候被自动调用
- 魔法方法的第一个参数应未cls(类方法)或者self(实例方法)
- cls:代表一个类的名称
- self:代表一个实例对象的名称
基本的魔法方法
__init__(self)
构造器,当一个实例被创建的时候调用的初始化方法
class Rectangle:
def __init__(self, x, y):
self.x = x
self.y = y
def getPeri(self):
return (self.x + self.y) * 2
def getArea(self):
return self.x * self.y
rect = Rectangle(4, 5)
print(rect.getPeri()) # 18
print(rect.getArea()) # 20
18
20
__new__(cls[, ...])
在一个对象实例化的时候所调用的第一个方法,在调用__init__
初始化前,先调用__new__
。__new__
至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init__
。__new__
对当前类进行了实例化,并将实例返回,传给__init__
的self。但是,执行了__new__
,并不一定会进入__init__
,只有__new__
返回了,当前类cls的实例,当前类的__init__
才会进入。
class A(object):
def __init__(self, value):
print("into A __init__")
self.value = value
def __new__(cls, *args, **kwargs):
print("into A __new__")
print(cls)
return object.__new__(cls)
class B(A):
def __init__(self, value):
print("into B __init__")
self.value = value
def __new__(cls, *args, **kwargs):
print("into B __new__")
print(cls)
return super().__new__(cls, *args, **kwargs)
b = B(10)
class A(object):
def __init__(self, value):
print("into A __init__")
self.value = value
def __new__(cls, *args, **kwargs):
print("into A __new__")
print(cls)
return object.__new__(cls)
class B(A):
def __init__(self, value):
print("into B __init__")
self.value = value
def __new__(cls, *args, **kwargs):
print("into B __new__")
print(cls)
return super().__new__(A, *args, **kwargs) # 改动了cls变为A
b = B(10)
into B __new__
<class '__main__.B'>
into A __new__
<class '__main__.B'>
into B __init__
into B __new__
<class '__main__.B'>
into A __new__
<class '__main__.A'>