Python之路,第十九篇:Python入门与基础19

时间:2023-03-08 22:18:52

python3  面向对象3

数值转换函数重载:

str(obj)              __str__

complex(x)       __complex__

int(obj)              __int__

float(obj)           __float__

bool                 __bool__

 class MyNumber:
def __init__(self,n):
self.data = n def __float__(self):
print("__float__被调用。")
try:
x = float(self.data)
except:
x = 0.0
return x n = MyNumber('')
print(float(n)) #__float__被调用。 #100.0 print(float("100.0")) #100.0
print(float(True)) #1.0 n = MyNumber(1+2j)
print(float(n)) #__float__被调用。 #0.0

bool 测试运算符重载:

方法格式:def   __bool__(self):

.......

作用:1, 用于if 语句的真值表达式中:

2, 用于while   语句的真值表达式中;

3,用于bool(obj) 函数取值;

说明:当没有__bool__ (self)方法时, 真值测试将以__len__(self)的方法的返回值来进行测试布尔值;

 class MyList:
def __init__(self, count=0, value =0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def __bool__(self):
print("__bool__被调用")
for x in self.data:
if x:
return True #如果遇到一个真值,直接返回true,不在执行下面的语句
return False #myl = MyList(10)
#print(myl) #MyList([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) #__bool__被调用 #MyList为假值
myl = MyList(10,1)
print(myl)
if myl:
print("MyList 为真值")
else:
print("MyList为假值")
#MyList([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
#__bool__被调用
#MyList 为真值
#
 class MyList:
def __init__(self, count=0, value =0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def __len__(self):
return len(self.data)
#def __bool__(self): #如果有__len__存在,__bool__优先执行;
# print("__bool__被调用")
# for x in self.data:
# if x:
# return True #如果遇到一个真值,直接返回true,不在执行下面的语句
# return False #myl = MyList(10)
#print(myl)#MyList([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
# MyList 为真值
myl = MyList(10,1)
print(myl)
if myl:
print("MyList 为真值")
else:
print("MyList为假值")
#MyList([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
#MyList 为真值

in   / not  in 运算符重载:

重载方法:

def    __contains__(self,  e):

pass

 class even:
"偶数类,用于显示偶数的有序列表"
def __init__(self, begin, end):
self.begin = begin
self.end = end #不包含end def __contains__(self, e):
print("__contains__被调用")
if e < self.begin:
return False if e >= self.end:
return False if e % 2 == 0:
return True return False e1 = even(1, 10)
if 4 in e1:
print("4 在e1中") if 3 in e1:
print("3 在e1中")
else:
print("3 不在e1中") if 30 not in even(10, 20):
print("30不在even(10, 20)中") #__contains__被调用
#4 在e1中
#__contains__被调用
#3 不在e1中
#__contains__被调用
#30不在even(10, 20)中

练习1:定义一个素数的类;

 class Primes:
def __init__(self, end):
"""end 用于表示素数的终止点,素数的起点是2包含2"""
self.end = end def __contains__(self, element):
def isprime(x):
for i in range(2, x):
if x % 2 == 0:
return False
return True
if element < 2:
return False
if element >= self.end:
return False
return isprime(element) p1 = Primes(100)
if 50 in p1:
print("50是素数")
else:
print("50不是素数"
 def isprime(x):
for i in range(2, x):
if x % 2 == 0:
return False
return True
class Primes:
def __init__(self, end):
"""end 用于表示素数的终止点,素数的起点是2包含2"""
self.end = end def __contains__(self, element):
#def isprime(x):
# for i in range(2, x):
# if x % 2 == 0:
# return False
# return True if element < 2:
return False
if element >= self.end:
return False
return isprime(element) p1 = Primes(100)
if 50 in p1:
print("50是素数")
else:
print("50不是素数")
 class Primes:
def __init__(self, end):
"""end 用于表示素数的终止点,素数的起点是2包含2"""
self.end = end @staticmethod
def isprime(x):
for i in range(2, x):
if x % 2 == 0:
return False
return True def __contains__(self, element):
#def isprime(x):
# for i in range(2, x):
# if x % 2 == 0:
# return False
# return True if element < 2:
return False
if element >= self.end:
return False
return self.isprime(element) p1 = Primes(100)
if 50 in p1:
print("50是素数")
else:
print("50不是素数")

索引和切片运算符的重载:

__getitem__(self, i)             # 索引/切片获取值

__getitem__(self, i , value)   #设置索引或切片的值;

__delitem__(self, i)               #进行删除索引操作

作用:让自定义的对象能进行索引和切片操作;

 class MyList:
def __init__(self, count=0, value=0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def setValueAt(self,index, value):
self.data[index] = value
#return self myl = MyList(5, 1)
print(myl) #MyList([1, 1, 1, 1, 1])
#myl[1] = 2
#print(myl.setValueAt(1, 2)) #return self
myl.setValueAt(1, 2)
print(myl)
===========================
class MyList:
def __init__(self, count=0, value=0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" #def setValueAt(self,index, value):
# self.data[index] = value
# #return self
def __setitem__(self, index, value):
self.data[index] = value myl = MyList(5, 1)
print(myl) #MyList([1, 1, 1, 1, 1]) myl[1] = 2
print(myl) #MyList([1, 2, 1, 1, 1])
 class MyList:
def __init__(self, count=0, value=0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def __setitem__(self, index, value):
self.data[index] = value def __getitem__(self, index):
print("__getitem__被调用")
return self.data[index] myl = MyList(5, 1)
print(myl) #MyList([1, 1, 1, 1, 1]) myl[1] = 2
print(myl) #MyList([1, 2, 1, 1, 1])
#
print(myl[0]) #__getitem__被调用, #1
 class MyList:
def __init__(self, count=0, value=0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def __setitem__(self, index, value):
self.data[index] = value def __getitem__(self, index):
print("__getitem__被调用")
return self.data[index] def __delitem__(self, index):
if index >= len(self.data):
raise IndexError("%d在不予许的范围内" % index) if index < -len(self.data):
raise IndexError("%d在不予许的范围内" % index)
del self.data[index]
#以下示意不予许用del,进行索引操作
#print("__delitem__被调用,index:", index)
#print("del 啥也不做!")
#raise TypeError myl = MyList(5, 1)
print(myl) #MyList([1, 1, 1, 1, 1]) myl[1] = 2
print(myl) #MyList([1, 2, 1, 1, 1])
#
print(myl[0]) #__getitem__被调用, #1
#
print(myl)
del myl[3]
print(myl)
#MyList([1, 2, 1, 1, 1])
#MyList([1, 2, 1, 1])

步长

 class MyList:
def __init__(self, count=0, value=0):
self.data = []
for x in range(count):
self.data.append(value) def __repr__(self):
return "MyList("+ repr(self.data) +")" def __setitem__(self, index, value):
self.data[index] = value def __getitem__(self, index):
print("__getitem__被调用,index:",index)
if isinstance(index, int):
return self.data[index]
elif isinstance(index, slice):
print("开始值是:", index.start)
print("结束值是:", index.stop)
print("步长是:", index.step) def __delitem__(self, index):
if index >= len(self.data):
raise IndexError("%d在不予许的范围内" % index) if index < -len(self.data):
raise IndexError("%d在不予许的范围内" % index)
del self.data[index]
#以下示意不予许用del,进行索引操作
#print("__delitem__被调用,index:", index)
#print("del 啥也不做!")
#raise TypeError myl = MyList(5, 1)
print(myl) #MyList([1, 1, 1, 1, 1])
myl[1] = 2
myl[2] = 3
myl[3] = 4
myl[4] = 5
print(myl) #MyList([1, 2, 3, 4, 5])
print(myl[1])
print(myl[1:5:2]) #__getitem__被调用,index: slice(1, 5, 2)#[2, 4] L = [1,2,3,4,5,6,7,8,9]
print(L[1::2]) #[2, 4, 6, 8]
s = slice(1,10,2)
print(L[s]) ##[2, 4, 6, 8]
print(s.start) #
print(s.stop) #
print(s.step) #
print()
print(myl[slice(1,5,2)])
print(myl[:])

函数调用(模拟)重载:

__call__ 方法:

作用:让一个对象能像函数一样被调用;

方法格式: def __call__(self, 参数列表):

执行代码

注: 此重载方法的参数可以是1个或多个()

例: class  A:

pas

a  = A()  #创建对象

a()  #??/a能被调用吗?

 class MySum:
def __init__(self):
self.data = 0 def __call__(self, *args, **kwargs):
#def __call__(self):
#def __call__(self, a, b):
"函数调用重载"
print("__call__被调用")
print("args",args, "kwargs",kwargs)
s = sum(args)
self.data += s
return s ms = MySum()
r = ms(100, 200)
print("r:",r)
r = ms(300, 400)
print("r:",r)
print("以前所有数之和:",ms.data)
#__call__被调用
#args (100, 200) kwargs {}
#r: 300
#__call__被调用
#args (300, 400) kwargs {}
#r: 700
#以前所有数之和: 1000#

迭代器(高级)

迭代器协议: 是指对象(实例)能够使用next函数获取下项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定;

next(it)  对应 __next__(self) 方法

iter(obj)   对应  __iter__(self)方法通常返回一个可迭代对象;

xxx

for 语句和推导式,先调用iter(obj)拿出迭代器,再迭代;

迭代器:

range() 生成器函数:

(x  for x in range(10) )  生成器表达式

迭代器协议:

1, 要有 __next__方法;

2, 无法取值产生StopIteration异常;

获取迭代器的方法;

__iter__方法,对象用于方法迭代器;

 class Odd:
def __init__(self, begin, end):
self.begin = begin
self.end = end
self.cur = begin #数据的当前位置 def __next__(self):
print("__next__被调用")
if self.cur >= self.end:
raise StopIteration
if self.cur % 2 == 0:
self.cur += 1
r = self.cur
self.cur += 2
return r def __iter__(self):
print("__iter__被调用,返回字节作为迭代器")
self.cur = self.begin
return self #o = Odd(1, 10)
o = Odd(2, 10) # 奇数对象
for x in iter(o):
print(x) print([x for x in o])
#print(next(o))#1
#print(next(o))#3
#print(next(o))#5
#print(next(o))#7
#print(next(o))#9
#print(next(o))
#__iter__被调用,返回字节作为迭代器
#__iter__被调用,返回字节作为迭代器
#__next__被调用
#
#__next__被调用
#
#__next__被调用
#
#__next__被调用
#
#__next__被调用
#__iter__被调用,返回字节作为迭代器
#__next__被调用
#__next__被调用
#__next__被调用
#__next__被调用
#__next__被调用
#[3, 5, 7, 9]
#
L = [1,2,3]
it = iter(L)
id(it) == id(L)
False
it
<list_iterator object at 0x0000000003D10940>
L
[1, 2, 3]

异常(高级)

with 语句

语法: with 表达式 [ as  变量名 ]:

语句块

或:

with   表达式1 [ as 变量名1 ] [ ,表达式2 [ as 变量名2 ]....]:

语句块

说明:as 子句中的变量绑定生成的对象;

 #f = open("file.txt",'r')
#while True:
# l = f.readline()
# print(l, end='')
# if len(l) == 0:
# break
#
#####
with open('file.txt','r') as f:
while True:
#3/0 #触发异常,但文件肯定会关闭
l = f.readline()
print(l, end='')
if len(l) == 0:
break

作用:使用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的“清理” 操作,并释放资源;

环境管理器:

1,类内有__enter__ 和__exit__ 方法的类被称为环境管理器;

2,能够用with 语句进行管理的对象必须是环境管理器;

3,__enter__将进入with语句时被调用并返回由as变量管理对象;

4, __exit__ 将在离开with 时被调用, 且可以用参数来判断在离开with语句时是否有异常发生,并且做出相应的处理;

 class Cooker:
def open_c(self):
print("正在打开火") def close_c(self):
print("正在关闭火") def doworks(self):
print("正在做饭") def __enter__(self):
self.open_c()
return self #此对象将被as绑定 def __exit__(self, exc_type, exc_val, exc_tb):
self.close_c()
if exc_type is None:
print("with语句正常退出")
else:
print("with语句异常退出", exc_val) with Cooker() as c:
c.doworks()
3/0
c.doworks() #正在打开火
#正在做饭
#正在关闭火
#Traceback (most recent call last):
# File "C:, line 23, in <module>
# 3/0
#ZeroDivisionError: division by zero# #正常处理
#c = Cooker()
#c.open_c()
#c.doworks()
#3/0
#c.doworks()
#c.close_c()

什么是继承(inheritance)/派生(derived)

什么是继承/派生

继承的目的是延续旧的功能;

派生的目的是在类旧类的基础上添加新的功能;

作用: 用继承派生机制,可以将一些共有功能加在基类中,实现代码共享,在不改变超类的代码的基础上改变原有功能;

名词: 基类(base class)/  超类(supper  class) /父类 (father class) /派生类(derived class) / 子类 (child  class)

单继承语法:

class    类名(超类名):

。。。。

继承说明:任何类都直接或间接的继承自object类;   object类是一切类的超类;

__base__属性:

作用:用来记录此类的基类(类实例);

覆盖override  (也叫重写 overrite)

什么是覆盖:

覆盖是指由继承关系的类中,子类中实现了与基类(超类)同名的方法,在子类实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫做覆盖;

子类对象显示调用基类方法的方式:

基类名。方法名。(实例,参数)

 class Human:
def say(self):
print("say: hello,world!") def run(self, speed):
print("Human run km/h speed:", speed) class Student(Human):
def study(self, s):
print("Student study:", s) def run(self, speed):
print("Student run km/h speed:", speed) def walk(self, speed): #走的方法
#self.run(speed) #调用自身self #Student run km/h speed: 3
#self.__class__.run(self, speed) #调用自身 #self #Student run km/h speed: 3
self.__class__.__base__.run(self, speed) #借助于self自身调用父类的run方法
# #Human run km/h speed: 3 t1 = Human()
s1 = Student() t1.run(5)
s1.run(4)#Student run km/h speed: 4 #此时调用的是子类的覆盖版本的方法 #子类调用基类的版本(原版本)方法
Human.run(s1, 8) # Human run km/h speed: 8 s1.walk(3) #Student run km/h speed: 3
 class Human:
def say(self):
print("say: hello,world!") def run(self, speed):
print("Human run km/h speed:", speed) class Teacher(Human):
def teach(self, te):
print("Teacher teach:", te) #def run(self, speed):
# print("Teacher run km/h speed:", speed) class Student(Teacher):
def study(self, s):
print("Student study:", s) #def run(self, speed):
# print("Student run km/h speed:", speed) def walk(self, speed): #走的方法
#self.run(speed) #调用自身self #Student run km/h speed: 3
#self.__class__.run(self, speed) #调用自身 #self #Student run km/h speed: 3
self.__class__.__base__.run(self, speed) #借助于self自身调用父类的run方法
# #Human run km/h speed: 3 t1 = Human()
t2 = Teacher()
s1 = Student() t1.run(5)
#s1.run(4)#Student run km/h speed: 4 #此时调用的是子类的覆盖版本的方法
t2.run(3.5)
s1.run(4) #子类调用基类的版本(原版本)方法
#Human.run(s1, 8) # Human run km/h speed: 8
#
#s1.walk(3) #Student run km/h speed: 3