Python 面向对象编程 类的高级用法以及异常处理
本文的Python知识基于 Python3
类的高级使用
类对象的动态绑定
类对象可以动态的绑定变量和方法
- 如果要绑定方法, 需要方法有
self参数 - 否则可能会不能调用类内部的成员
- 如果要绑定方法, 需要方法有
对象动态绑定的成员, 只存在于当前绑定的对象
- 其他对象不受影响
>>> 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'
>>> 类的限定绑定
动态绑定会给我们带来极大的便利, 同时, 也会带来一些不便
比如, 我只是单纯的想给对象赋值, 但是手误, 将对象的属性写错了
此时, 赋值失败, 并且绑定了一个无关的变量
- 为了解决这个问题, Python提供了绑定限制
- 可以规定只允许绑定的变量
>>> 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的
__str__方法- print的时候会去调用__str__方法
实现class的
__repr__方法- 调试输出就会自动去调用__repr__方法
>>> 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 .. 的语句
实现
__iter__和__next__函数- in的时候会调用 iter
- for的时候会不断调用 next
>>> 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__
>>> 对象响应下标和切片操作
实现
__getitem__方法- 需要进行判定
- 然后决定返回下标和切片
>>> 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__
切片
>>> 对象的可调用操作
- 实现
__call__函数, 对象就能像方法一样调用
>>> 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....
>>> 类的构造和析构
__init__是构造方法__del__是析构方法
枚举类型
Python里是有枚举类型的
- 需要from enum import Enum
>>> 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'
>>> 抛出异常
有时候, 我们需要把异常抛出去
或者需要结束一个迭代
- 使用
raise抛出异常 - 可以抛出新异常
- 可以抛出捕获到的异常
>>> 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)
>>> 未完待续...
如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-07-22 at 03:32 pm