PoEdu培训 Python班 第十课 Python 面向对象编程 类的高级用法以及异常处理
文章类别: 培训笔记 0 评论

PoEdu培训 Python班 第十课 Python 面向对象编程 类的高级用法以及异常处理

文章类别: 培训笔记 0 评论

Python 面向对象编程 类的高级用法以及异常处理

本文的Python知识基于 Python3

类的高级使用

类对象的动态绑定

>>> class user_info(object):
...     pass
... 
>>> def foo():
...     print('foo')
... 
>>> def foo_class(self):
...     print(self.name)
... 
>>> u = user_info()
>>> uu = user_info()
>>> u.name = 'root'
>>> u.pwd = 'admin'
>>> u.foo = foo
>>> u.foo_class = foo_class
>>> u.name
'root'
>>> u.pwd
'admin'
>>> u.foo()
foo
>>> u.foo_class()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo_class() missing 1 required positional argument: 'self'
>>> uu.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'name'
>>> uu.pwd
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'pwd'
>>> uu.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'foo'
>>> uu.foo_class()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'foo_class'
>>> u2 = user_info()
>>> u2.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'name'
>>> u2.pwd
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'pwd'
>>> u2.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'foo'
>>> u2.foo_class()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'foo_class'
>>> 

类的绑定

>>> class user_info(object):
...     pass
... 
>>> u = user_info()
>>> u.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'name'
>>> user_info.name = 'aaa'
>>> user_info.name
'aaa'
>>> u2 = user_info()
>>> u2.name
'aaa'
>>> u.name
'aaa'
>>> user_info.name = 'bbb'
>>> user_info.name
'bbb'
>>> u3 = user_info()
>>> u3.name
'bbb'
>>> u2.name
'bbb'
>>> u.name
'bbb'
>>> u.name = 'a'
>>> u2.name = 'b'
>>> user_info.name = 'abc'
>>> u.name
'a'
>>> u2.name
'b'
>>> u3.name
'abc'
>>> user_info.name
'abc'
>>> del(user_info.name)
>>> 
>>> user_info.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'user_info' has no attribute 'name'
>>> u.name
'a'
>>> u2.name
'b'
>>> u3.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'user_info' object has no attribute 'name'
>>> 

类的静态成员

>>> class user_info(object):
...     company = 'HadesStudio'     # 类的静态成员
... 
>>> user_info.company   # 访问静态成员
'HadesStudio'
>>> user = user_info()
>>> user.company
'HadesStudio'
>>> user2 = user_info()
>>> user2.company
'HadesStudio'
>>> user.company = 'hadesstudio'
>>> user.company
'hadesstudio'
>>> user2.company
'HadesStudio'
>>> user_info.company = 'HXHLB'
>>> user.company
'hadesstudio'
>>> user2.company
'HXHLB'
>>> 

类的限定绑定

动态绑定会给我们带来极大的便利, 同时, 也会带来一些不便
比如, 我只是单纯的想给对象赋值, 但是手误, 将对象的属性写错了
此时, 赋值失败, 并且绑定了一个无关的变量

>>> class cls_demo(object):
...     __slots__ = ('name', 'pwd')     # 只允许绑定 name 和 pwd
... 
>>> demo1 = cls_demo()
>>> demo1.user = 'root'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'cls_demo' object has no attribute 'user'
>>> demo1.name = 'admin'
>>> demo1.name
'admin'
>>> 

类的特性/属性

Python号称优雅的编程语言, 然而我们写的代码却不是那么优雅
昨天我们编写的class中, 私有变量的访问是通过get和set方法来实现的
那么有没有优雅的实现, 类似 u.name = 'admin', print(u.name)
并且name在类中还是__name呢?

>>> class user_info(object):
...     def __init__(self, name, pwd):
...         self.__name = name
...         self.__pwd = pwd
... 
...     @property
...     def name(self):         # 特性, 只读
...         return self.__name
...     @name.setter
...     def name(self, val):    # 特性, 只写
...         self.__name = val
... 
>>> u = user_info('root', 'admin')
>>> print(u.name)
root
>>> u.name = 'hxhlb'
>>> print(u.name)
hxhlb
>>> 

类对象的直接打印和调试输出

上节课我们的程序, 是通过在class里定义一个print函数实现的
有没有方法可以直接print(对象)这样的方式呢?
我们在控制台下的时候, 直接输入对象名称可以显示内容, 这样又怎么实现呢?

>>> class user_info(object):
...     def __init__(self, name, pwd):
...         self.__name = name
...         self.__pwd = pwd
... 
...     def __str__(self):      # 直接让print方法来打印 print自动调用此方法
...         return '__str__'
... 
...     def __repr__(self, **kwargs):
...         return '__repr__'
... 
>>> u = user_info('root', 'admin')
>>> print(u)
__str__
>>> u       # 调试输出
__repr__
>>> 

遍历对象

让对象可以和list, dict, tuple等一样可以进行 for .. in .. 的语句

>>> import random
>>> class user_info(object):
...     def __init__(self, name, pwd):
...         self.__name = name
...         self.__pwd = pwd
...         self.__loop = 10
... 
...     def __iter__(self):
...         print('__iter__')
...         self.__loop = 10    # 规定迭代次数
...         return self         # 自身就可遍历就直接返回
... 
...     def __next__(self):
...         print('__next__')
...         ret = random.randint(1, 1000)
...         self.__loop -= 1
...         if not self.__loop:
...             raise StopIteration()   # 停止迭代
...         return ret
... 
>>> u = user_info('root', 'admin')
>>> for i in u:
...     print(i)
... 
__iter__
__next__
142
__next__
498
__next__
909
__next__
353
__next__
829
__next__
784
__next__
629
__next__
682
__next__
595
__next__
>>> 

对象响应下标和切片操作

>>> class user_info(object):
...     def __init__(self, name, pwd):
...         self.__name = name
...         self.__pwd = pwd
...         self.__loop = 10
... 
...     def __getitem__(self, item):    # 下标操作或切片
...         print("__getitem__")
...         if isinstance(item, int):
...             return item
...         if isinstance(item, slice):
...             return '切片'
... 
>>> u = user_info('root', 'admin')
>>> print(u[0])
__getitem__
0
>>> print(u[1])
__getitem__
1
>>> print(u[1:10])
__getitem__
切片
>>> print(u[1:10:2])
__getitem__
切片
>>> 

对象的可调用操作

>>> class user_info(object):
...     def __init__(self, name, pwd):
...         self.__name = name
...         self.__pwd = pwd
...         self.__loop = 10
... 
...     def __call__(self):    # 可执行
...         print("__call__")
... 
>>> u = user_info('root', 'admin')
>>> u()
__call__
>>> 

call的应用, 来一个简单的包装器

>>> class check_foo(object):
...     def __init__(self, foo):
...         self.__foo = foo
...     def __call__(self):
...         print('验证...')
...         self.__foo()
... 
>>> ck_foo = check_foo(lambda : print('test foo....'))
>>> ck_foo()
验证...
test foo....
>>> 

类的构造和析构

枚举类型

Python里是有枚举类型的

>>> from enum import Enum, unique
>>> cc = Enum('Color', ('red', 'green', 'blue'))
>>> print(cc)
<enum 'Color'>
>>> print(cc.red)
Color.red
>>> @unique                 # 检测重复
... class color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
... 
>>> c = color.RED
>>> print(c)
color.RED
>>> print(c.RED)
color.RED
>>>

Python的错误处理

使用if判定

使用if判定配合循环, 直到符合条件

>>> name = ''
>>> while not len(name):
...     name = input('Input your name:')
... 
Input your name:

Input your name:

Input your name:

Input your name:

Input your name:
12
>>> 

使用 try excpt finally

基础使用

>>> age = -1
>>> while age == -1:
...     tmp = input('Input your age:')
...     try:
...         age = int(tmp)
...     except:
...         print('Catch Error, continue run...')
...         are = -1
... 
Input your age:
a

Catch Error, continue run...
Input your age:
ea

Catch Error, continue run...
Input your age:
ad

Catch Error, continue run...
Input your age:
ad

Catch Error, continue run...
Input your age:
ad

Catch Error, continue run...
Input your age:
1

>>> 

按照异常捕获, 获取异常源

>>> try:
...     f = open(input('filename:'))
...     age = int(input("int:"))
...     f.close()
... except ValueError:
...     print('int Error')
... except IOError:
...     print('open Error')
... 
filename:
xx

open Error
>>> 

finally处理无论如何都有执行的代码

>>> try:
...     f = open(input('filename:'), 'w')
...     age = int(input("int:"))
... except ValueError:
...     print('int Error')
... except IOError:
...     print('open Error')
... finally:
...     f.close()
... 
filename:
xxx.xxx

int:
asdf

int Error
>>> 

输出具体异常信息

>>> f = None
>>> try:
...     f = open(input('filename:'), 'w')
...     age = int(input("int:"))
... except ValueError as e:
...     print('int Error', e)
... except IOError as e:
...     print('open Error', e)
... finally:
...     if f:
...         f.close()
... 
filename:
xxx.xxx

int:
asdf

int Error invalid literal for int() with base 10: 'asdf'
>>> 

捕获所有异常

Lesson010 交互窗口 [PTVS 3.0.17179.1-15.0]
键入 $help 获取命令列表。
>>> f = None
>>> try:
...     f = open(input('filename:'), 'w')
...     age = int(input("int:"))
... except Exception as e:
...     print('Error', e)
... finally:
...     if f:
...         f.close()
... 
filename:
xxx.xxx

int:
as

Error invalid literal for int() with base 10: 'as'
>>> 

抛出异常

有时候, 我们需要把异常抛出去
或者需要结束一个迭代

>>> def div(x, y):
...     if y == 0:
...         raise ValueError('被除数为0')
...     else:
...         return x / y
... 
>>> div(1, 2)
0.5
>>> div(1, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in div
ValueError: 被除数为0
>>> 
# =============分割线================
>>> def convert_to_num(str):
...     try:
...         return int(str)
...     except Exception as e:
...         raise e
... 
>>> try:
...     convert_to_num(10)
...     convert_to_num('abc')
... except Exception as e:
...     print(e)
...     print(e.with_traceback())
... 
10
invalid literal for int() with base 10: 'abc'
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "<stdin>", line 5, in convert_to_num
  File "<stdin>", line 3, in convert_to_num
ValueError: invalid literal for int() with base 10: 'abc'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
TypeError: with_traceback() takes exactly one argument (0 given)
>>> 

未完待续...

如有错误,请提出指正!谢谢.

回复