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

python3  面向对象3

数值转换函数重载:

str(obj)              __str__

complex(x)       __complex__

int(obj)              __int__

float(obj)           __float__

bool                 __bool__

 1 class MyNumber:
 2     def __init__(self,n):
 3         self.data = n
 4 
 5     def __float__(self):
 6         print("__float__被调用。")
 7         try:
 8             x = float(self.data)
 9         except:
10             x = 0.0
11         return x
12 
13 
14 n = MyNumber('100')
15 print(float(n))  #__float__被调用。   #100.0
16 
17 print(float("100.0"))  #100.0
18 print(float(True))  #1.0
19 
20 n = MyNumber(1+2j)
21 print(float(n)) #__float__被调用。  #0.0
View Code

 

bool 测试运算符重载:

方法格式:def   __bool__(self):

                            .......

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

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

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

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

 

 1 class MyList:
 2     def __init__(self, count=0, value =0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def __bool__(self):
11         print("__bool__被调用")
12         for x in self.data:
13             if x:
14                 return True #如果遇到一个真值,直接返回true,不在执行下面的语句
15         return False
16 
17 
18 #myl = MyList(10)
19 #print(myl)  #MyList([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) #__bool__被调用 #MyList为假值
20 myl = MyList(10,1)
21 print(myl)
22 if myl:
23     print("MyList 为真值")
24 else:
25     print("MyList为假值")
26 #MyList([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
27 #__bool__被调用
28 #MyList 为真值
29 #
View Code

 

 1 class MyList:
 2     def __init__(self, count=0, value =0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def __len__(self):
11         return len(self.data)
12     #def __bool__(self): #如果有__len__存在,__bool__优先执行;
13     #    print("__bool__被调用")
14     #    for x in self.data:
15     #        if x:
16     #            return True #如果遇到一个真值,直接返回true,不在执行下面的语句
17     #    return False
18 
19 
20 #myl = MyList(10)
21 #print(myl)#MyList([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
22            #   MyList 为真值
23 myl = MyList(10,1)
24 print(myl)
25 if myl:
26     print("MyList 为真值")
27 else:
28     print("MyList为假值")
29 #MyList([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
30 #MyList 为真值
View Code

 

in   / not  in 运算符重载:

重载方法:

def    __contains__(self,  e):

         pass

 1 class even:
 2     "偶数类,用于显示偶数的有序列表"
 3     def __init__(self, begin, end):
 4         self.begin = begin
 5         self.end = end #不包含end
 6 
 7     def __contains__(self, e):
 8         print("__contains__被调用")
 9         if e < self.begin:
10             return False
11 
12         if e >= self.end:
13             return False
14 
15         if e % 2 == 0:
16             return True
17 
18         return False
19 
20 e1 = even(1, 10)
21 if 4 in e1:
22     print("4 在e1中")
23 
24 if 3 in e1:
25     print("3 在e1中")
26 else:
27     print("3 不在e1中")
28 
29 if 30 not in even(10, 20):
30     print("30不在even(10, 20)中")
31 
32 #__contains__被调用
33 #4 在e1中
34 #__contains__被调用
35 #3 不在e1中
36 #__contains__被调用
37 #30不在even(10, 20)中
View Code

 

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

 1 class Primes:
 2     def __init__(self, end):
 3         """end 用于表示素数的终止点,素数的起点是2包含2"""
 4         self.end = end
 5 
 6     def __contains__(self, element):
 7         def isprime(x):
 8             for i in range(2, x):
 9                 if x % 2 == 0:
10                     return False
11             return True
12         if element < 2:
13             return False
14         if element >= self.end:
15             return False
16         return isprime(element)
17     
18         
19 p1 = Primes(100)
20 if 50 in p1:
21     print("50是素数")
22 else:
23     print("50不是素数"
View Code
 1 def isprime(x):
 2     for i in range(2, x):
 3         if x % 2 == 0:
 4             return False
 5     return True
 6 class Primes:
 7     def __init__(self, end):
 8         """end 用于表示素数的终止点,素数的起点是2包含2"""
 9         self.end = end
10 
11     def __contains__(self, element):
12         #def isprime(x):
13         #    for i in range(2, x):
14         #        if x % 2 == 0:
15         #            return False
16         #    return True
17 
18         if element < 2:
19             return False
20         if element >= self.end:
21             return False
22         return isprime(element)
23 
24 
25 p1 = Primes(100)
26 if 50 in p1:
27     print("50是素数")
28 else:
29     print("50不是素数")
View Code
 1 class Primes:
 2     def __init__(self, end):
 3         """end 用于表示素数的终止点,素数的起点是2包含2"""
 4         self.end = end
 5 
 6     @staticmethod
 7     def isprime(x):
 8         for i in range(2, x):
 9            if x % 2 == 0:
10                return False
11         return True
12 
13     def __contains__(self, element):
14         #def isprime(x):
15         #    for i in range(2, x):
16         #        if x % 2 == 0:
17         #            return False
18         #    return True
19 
20         if element < 2:
21             return False
22         if element >= self.end:
23             return False
24         return self.isprime(element)
25 
26 
27 p1 = Primes(100)
28 if 50 in p1:
29     print("50是素数")
30 else:
31     print("50不是素数")
View Code

 

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

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

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

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

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

 1 class MyList:
 2     def __init__(self, count=0, value=0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def setValueAt(self,index, value):
11         self.data[index] = value
12         #return self
13 
14 myl = MyList(5, 1)
15 print(myl) #MyList([1, 1, 1, 1, 1])
16 #myl[1] = 2
17 #print(myl.setValueAt(1, 2)) #return self
18 myl.setValueAt(1, 2)
19 print(myl)
20 ===========================
21 class MyList:
22     def __init__(self, count=0, value=0):
23         self.data = []
24         for x in range(count):
25             self.data.append(value)
26 
27     def __repr__(self):
28         return "MyList("+ repr(self.data) +")"
29 
30     #def setValueAt(self,index, value):
31     #    self.data[index] = value
32     #    #return self
33     def __setitem__(self, index, value):
34         self.data[index] = value
35 
36 
37 myl = MyList(5, 1)
38 print(myl) #MyList([1, 1, 1, 1, 1])
39 
40 myl[1] = 2
41 print(myl)  #MyList([1, 2, 1, 1, 1])
View Code
 1 class MyList:
 2     def __init__(self, count=0, value=0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def __setitem__(self, index, value):
11         self.data[index] = value
12 
13     def __getitem__(self, index):
14         print("__getitem__被调用")
15         return self.data[index]
16 
17 myl = MyList(5, 1)
18 print(myl) #MyList([1, 1, 1, 1, 1])
19 
20 myl[1] = 2
21 print(myl)  #MyList([1, 2, 1, 1, 1])
22 #
23 print(myl[0]) #__getitem__被调用, #1
View Code

 

 1 class MyList:
 2     def __init__(self, count=0, value=0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def __setitem__(self, index, value):
11         self.data[index] = value
12 
13     def __getitem__(self, index):
14         print("__getitem__被调用")
15         return self.data[index]
16 
17     def __delitem__(self, index):
18         if index >= len(self.data):
19             raise IndexError("%d在不予许的范围内" % index)
20 
21         if index < -len(self.data):
22             raise IndexError("%d在不予许的范围内" % index)
23         del self.data[index]
24         #以下示意不予许用del,进行索引操作
25         #print("__delitem__被调用,index:", index)
26         #print("del 啥也不做!")
27         #raise TypeError
28 
29 myl = MyList(5, 1)
30 print(myl) #MyList([1, 1, 1, 1, 1])
31 
32 myl[1] = 2
33 print(myl)  #MyList([1, 2, 1, 1, 1])
34 #
35 print(myl[0]) #__getitem__被调用, #1
36 #
37 print(myl)
38 del myl[3]
39 print(myl)
40 #MyList([1, 2, 1, 1, 1])
41 #MyList([1, 2, 1, 1])
View Code

步长 

 1 class MyList:
 2     def __init__(self, count=0, value=0):
 3         self.data = []
 4         for x in range(count):
 5             self.data.append(value)
 6 
 7     def __repr__(self):
 8         return "MyList("+ repr(self.data) +")"
 9 
10     def __setitem__(self, index, value):
11         self.data[index] = value
12 
13     def __getitem__(self, index):
14         print("__getitem__被调用,index:",index)
15         if isinstance(index, int):
16             return self.data[index]
17         elif isinstance(index, slice):
18             print("开始值是:", index.start)
19             print("结束值是:", index.stop)
20             print("步长是:", index.step)
21 
22 
23     def __delitem__(self, index):
24         if index >= len(self.data):
25             raise IndexError("%d在不予许的范围内" % index)
26 
27         if index < -len(self.data):
28             raise IndexError("%d在不予许的范围内" % index)
29         del self.data[index]
30         #以下示意不予许用del,进行索引操作
31         #print("__delitem__被调用,index:", index)
32         #print("del 啥也不做!")
33         #raise TypeError
34 
35 myl = MyList(5, 1)
36 print(myl) #MyList([1, 1, 1, 1, 1])
37 myl[1] = 2
38 myl[2] = 3
39 myl[3] = 4
40 myl[4] = 5
41 print(myl) #MyList([1, 2, 3, 4, 5])
42 print(myl[1])
43 print(myl[1:5:2]) #__getitem__被调用,index: slice(1, 5, 2)#[2, 4]
44 
45 L = [1,2,3,4,5,6,7,8,9]
46 print(L[1::2]) #[2, 4, 6, 8]
47 s = slice(1,10,2)
48 print(L[s])    ##[2, 4, 6, 8]
49 print(s.start) #1
50 print(s.stop)  #10
51 print(s.step)  #2
52 print()
53 print(myl[slice(1,5,2)])
54 print(myl[:])
View Code

 

 

函数调用(模拟)重载:

__call__ 方法:

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

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

                             执行代码

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

例: class  A:

               pas

a  = A()  #创建对象

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

 1 class MySum:
 2     def __init__(self):
 3         self.data = 0
 4 
 5     def __call__(self, *args, **kwargs):
 6     #def __call__(self):
 7     #def __call__(self, a, b):
 8         "函数调用重载"
 9         print("__call__被调用")
10         print("args",args, "kwargs",kwargs)
11         s = sum(args)
12         self.data += s
13         return s
14 
15 
16 ms = MySum()
17 r = ms(100, 200)
18 print("r:",r)
19 r = ms(300, 400)
20 print("r:",r)
21 print("以前所有数之和:",ms.data)
22 #__call__被调用
23 #args (100, 200) kwargs {}
24 #r: 300
25 #__call__被调用
26 #args (300, 400) kwargs {}
27 #r: 700
28 #以前所有数之和: 1000#
View Code

 

迭代器(高级)

迭代器协议: 是指对象(实例)能够使用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__方法,对象用于方法迭代器;

 1 class Odd:
 2     def __init__(self, begin, end):
 3         self.begin = begin
 4         self.end = end
 5         self.cur = begin  #数据的当前位置
 6 
 7     def __next__(self):
 8         print("__next__被调用")
 9         if self.cur >= self.end:
10             raise StopIteration
11         if self.cur % 2 == 0:
12             self.cur += 1
13         r = self.cur
14         self.cur += 2
15         return r
16 
17     def __iter__(self):
18         print("__iter__被调用,返回字节作为迭代器")
19         self.cur = self.begin
20         return self
21 
22 #o = Odd(1, 10)
23 o = Odd(2, 10) # 奇数对象
24 for x in iter(o):
25     print(x)
26 
27 print([x for x in o])
28 #print(next(o))#1
29 #print(next(o))#3
30 #print(next(o))#5
31 #print(next(o))#7
32 #print(next(o))#9
33 #print(next(o))
34 #__iter__被调用,返回字节作为迭代器
35 #__iter__被调用,返回字节作为迭代器
36 #__next__被调用
37 #3
38 #__next__被调用
39 #5
40 #__next__被调用
41 #7
42 #__next__被调用
43 #9
44 #__next__被调用
45 #__iter__被调用,返回字节作为迭代器
46 #__next__被调用
47 #__next__被调用
48 #__next__被调用
49 #__next__被调用
50 #__next__被调用
51 #[3, 5, 7, 9]
52 #
53 L = [1,2,3]
54 it = iter(L)
55 id(it) == id(L)
56 False
57 it
58 <list_iterator object at 0x0000000003D10940>
59 L
60 [1, 2, 3]
View Code

 

 

异常(高级)

with 语句

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

                     语句块

         或:

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

                    语句块

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

 1 #f = open("file.txt",'r')
 2 #while True:
 3 #    l = f.readline()
 4 #    print(l, end='')
 5 #    if len(l) == 0:
 6 #        break
 7 #
 8 #####
 9 with open('file.txt','r') as f:
10     while True:
11         #3/0    #触发异常,但文件肯定会关闭
12         l = f.readline()
13         print(l, end='')
14         if len(l) == 0:
15             break
16             
View Code

 

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

 

环境管理器:

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

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

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

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

 1 class Cooker:
 2     def open_c(self):
 3         print("正在打开火")
 4 
 5     def close_c(self):
 6         print("正在关闭火")
 7 
 8     def doworks(self):
 9         print("正在做饭")
10 
11     def __enter__(self):
12         self.open_c()
13         return self  #此对象将被as绑定
14 
15     def __exit__(self, exc_type, exc_val, exc_tb):
16         self.close_c()
17         if exc_type is None:
18             print("with语句正常退出")
19         else:
20             print("with语句异常退出", exc_val)
21 
22 
23 with Cooker() as c:
24     c.doworks()
25     3/0
26     c.doworks()
27 
28 #正在打开火
29 #正在做饭
30 #正在关闭火
31 #Traceback (most recent call last):
32 #  File "C:, line 23, in <module>
33 #    3/0
34 #ZeroDivisionError: division by zero#
35 
36 
37 #正常处理
38 #c = Cooker()
39 #c.open_c()
40 #c.doworks()
41 #3/0
42 #c.doworks()
43 #c.close_c()
View Code

 

 

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

什么是继承/派生

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

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

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

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

单继承语法:

class    类名(超类名):

    。。。。

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

 

__base__属性: 

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

覆盖override  (也叫重写 overrite)

什么是覆盖:

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

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

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

 1 class Human:
 2     def say(self):
 3         print("say: hello,world!")
 4 
 5     def run(self, speed):
 6         print("Human run km/h speed:", speed)
 7 
 8 class Student(Human):
 9     def study(self, s):
10         print("Student study:", s)
11 
12     def run(self, speed):
13         print("Student run km/h speed:", speed)
14 
15     def walk(self, speed): #走的方法
16         #self.run(speed)       #调用自身self   #Student run km/h speed: 3
17         #self.__class__.run(self, speed) #调用自身  #self #Student run km/h speed: 3
18         self.__class__.__base__.run(self, speed) #借助于self自身调用父类的run方法
19                                                  # #Human run km/h speed: 3
20 
21 
22 t1 = Human()
23 s1 = Student()
24 
25 t1.run(5)
26 s1.run(4)#Student run km/h speed: 4 #此时调用的是子类的覆盖版本的方法
27 
28 #子类调用基类的版本(原版本)方法
29 Human.run(s1, 8) # Human run km/h speed: 8
30 
31 s1.walk(3) #Student run km/h speed: 3
View Code
 1 class Human:
 2     def say(self):
 3         print("say: hello,world!")
 4 
 5     def run(self, speed):
 6         print("Human run km/h speed:", speed)
 7 
 8 class Teacher(Human):
 9     def teach(self, te):
10         print("Teacher teach:", te)
11 
12     #def run(self, speed):
13     #    print("Teacher run km/h speed:", speed)
14 
15 class Student(Teacher):
16     def study(self, s):
17         print("Student study:", s)
18 
19     #def run(self, speed):
20     #    print("Student run km/h speed:", speed)
21 
22     def walk(self, speed): #走的方法
23         #self.run(speed)       #调用自身self   #Student run km/h speed: 3
24         #self.__class__.run(self, speed) #调用自身  #self #Student run km/h speed: 3
25         self.__class__.__base__.run(self, speed) #借助于self自身调用父类的run方法
26                                                  # #Human run km/h speed: 3
27 
28 
29 t1 = Human()
30 t2 = Teacher()
31 s1 = Student()
32 
33 t1.run(5)
34 #s1.run(4)#Student run km/h speed: 4 #此时调用的是子类的覆盖版本的方法
35 t2.run(3.5)
36 s1.run(4)
37 
38 
39 #子类调用基类的版本(原版本)方法
40 #Human.run(s1, 8) # Human run km/h speed: 8
41 #
42 #s1.walk(3) #Student run km/h speed: 3
View Code

 

posted on 2018-05-29 20:00  微子天明  阅读(189)  评论(0编辑  收藏  举报

导航