python重拾第七天-面向对象进阶
本节内容:
- 面向对象高级语法部分
- 经典类vs新式类
- 静态方法、类方法、属性方法
- 类的特殊方法
- 反射
- 异常处理
- Socket开发基础
- 作业:开发一个支持多用户在线的FTP程序
面向对象高级语法部分
经典类vs新式类
把下面代码用python2 和python3都执行一下
#_*_coding:utf-8_*_ class A:
def __init__(self):
self.n = 'A' class B(A):
# def __init__(self):
# self.n = 'B'
pass class C(A):
def __init__(self):
self.n = 'C' class D(B,C):
# def __init__(self):
# self.n = 'D'
pass obj = D() print(obj.n)
classical vs new style:
- 经典类:深度优先
- 新式类:广度优先
- super()用法
super(Foo,self).__init__(name,age)
静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
class Dog(object): def __init__(self,name):
self.name = name @staticmethod #把eat方法变为静态方法
def eat(self):
print("%s is eating" % self.name) d = Dog("ChenRonghua")
d.eat()
上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
Traceback (most recent call last):
File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/静态方法.py", line 17, in <module>
d.eat()
TypeError: eat() missing 1 required positional argument: 'self'
想让上面的代码可以正常工作有两种办法
1. 调用时主动传递实例本身给eat方法,即d.eat(d)
2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了
class Dog(object): def __init__(self,name):
self.name = name @staticmethod
def eat():
print(" is eating") d = Dog("ChenRonghua")
d.eat()
类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class Dog(object):
def __init__(self,name):
self.name = name @classmethod
def eat(self):
print("%s is eating" % self.name) d = Dog("ChenRonghua")
d.eat()
执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的
Traceback (most recent call last):
File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 16, in <module>
d.eat()
File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 11, in eat
print("%s is eating" % self.name)
AttributeError: type object 'Dog' has no attribute 'name'
此时可以定义一个类变量,也叫name,看下执行效果
class Dog(object):
name = "我是类变量"
def __init__(self,name):
self.name = name @classmethod
def eat(self):
print("%s is eating" % self.name) d = Dog("ChenRonghua")
d.eat() #执行结果 我是类变量 is eating
属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class Dog(object): def __init__(self,name):
self.name = name @property
def eat(self):
print(" %s is eating" %self.name) d = Dog("ChenRonghua")
d.eat()
调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了
Traceback (most recent call last):
ChenRonghua is eating
File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 16, in <module>
d.eat()
TypeError: 'NoneType' object is not callable
正常调用如下
d = Dog("ChenRonghua")
d.eat 输出
ChenRonghua is eating
好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过 定义 静态属性来实现的, 比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:
1. 连接航空公司API查询
2. 对查询结果进行解析
3. 返回结果给你的用户
因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以,明白 了么?
class Flight(object):
def __init__(self,name):
self.flight_name = name def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 1 @property
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later") f = Flight("CA980")
f.flight_status
ool , 那现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?试试吧
f = Flight("CA980")
f.flight_status
f.flight_status = 2
输出, 说不能更改这个属性,我擦。。。。,怎么办怎么办。。。
checking flight CA980 status
flight is arrived...
Traceback (most recent call last):
File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 58, in <module>
f.flight_status = 2
AttributeError: can't set attribute
当然可以改, 不过需要通过@proerty.setter装饰器再装饰一下,此时 你需要写一个新方法, 对这个flight_status进行更改。
class Flight(object):
def __init__(self,name):
self.flight_name = name def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 1 @property
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later") @flight_status.setter #修改
def flight_status(self,status):
status_dic = {
0 : "canceled",
1 :"arrived",
2 : "departured"
}
print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) ) @flight_status.deleter #删除
def flight_status(self):
print("status got removed...") f = Flight("CA980")
f.flight_status
f.flight_status = 2 #触发@flight_status.setter
del f.flight_status #触发@flight_status.deleter
注意以上代码里还写了一个@flight_status.deleter, 是允许可以将这个属性删除
类的特殊成员方法
1. __doc__ 表示类的描述信息
class Foo:
""" 描述类信息,这是用于看片的神奇 """ def func(self):
pass print Foo.__doc__
#输出:类的描述信息
2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class C: def __init__(self):
self.name = 'wupeiqi'
lib/aa.py
from lib.aa import C obj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类
index.py
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self):
pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__
obj() # 执行 __call__
6. __dict__ 查看类或对象中的所有成员
class Province: country = 'China' def __init__(self, name, count):
self.name = name
self.count = count def func(self, *args, **kwargs):
print 'func' # 获取类的成员,即:静态字段、方法、
print Province.__dict__
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None} obj1 = Province('HeBei',10000)
print obj1.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'} obj2 = Province('HeNan', 3888)
print obj2.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Foo: def __str__(self):
return 'alex li' obj = Foo()
print obj
# 输出:alex li
8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo(object): def __getitem__(self, key):
print('__getitem__',key) def __setitem__(self, key, value):
print('__setitem__',key,value) def __delitem__(self, key):
print('__delitem__',key) obj = Foo() result = obj['k1'] # 自动触发执行 __getitem__
obj['k2'] = 'alex' # 自动触发执行 __setitem__
del obj['k1']
9. __new__ \ __metaclass__
class Foo(object): def __init__(self,name):
self.name = name f = Foo("alex")
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
print type(f) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type 'type'> 表示,Foo类对象由 type 类创建
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a). 普通方式
class Foo(object): def func(self):
print 'hello alex'
b). 特殊方式
def func(self):
print 'hello wupeiqi' Foo = type('Foo',(object,), {'func': func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员
def func(self):
print("hello %s"%self.name) def __init__(self,name,age):
self.name = name
self.age = age
Foo = type('Foo',(object,),{'func':func,'__init__':__init__}) f = Foo("jack",22)
f.func()
加上构造方法
So ,孩子记住,类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
class MyType(type):
def __init__(self, *args, **kwargs):
print("Mytype __init__", *args, **kwargs) def __call__(self, *args, **kwargs):
print("Mytype __call__", *args, **kwargs)
obj = self.__new__(self)
print("obj ", obj, *args, **kwargs)
print(self)
self.__init__(obj, *args, **kwargs)
return obj def __new__(cls, *args, **kwargs):
print("Mytype __new__", *args, **kwargs)
return type.__new__(cls, *args, **kwargs) print('here...') class Foo(object, metaclass=MyType): def __init__(self, name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs):
print("Foo __new__", cls, *args, **kwargs)
return object.__new__(cls) f = Foo("Alex")
print("f", f) print("fname", f.name)
自定义元素
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好
反射
通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
getattr(object, name, default=None)
判断object中有没有一个name字符串对应的方法或属性
hasattr(object,name)
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v''
setattr(x, y, v)
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
"""
delattr(x, y)
class Foo(object): def __init__(self):
self.name = 'wupeiqi' def func(self):
return 'func' obj = Foo() # #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func') # #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func') # #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1) # #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')
反射代码示例
其他
一、isinstance(obj, cls)
检查是否obj是否是类 cls 的对象
class Foo(object):
pass obj = Foo() isinstance(obj, Foo)
二、issubclass(sub, super)
检查sub类是否是 super 类的派生类
class Foo(object):
pass class Bar(Foo):
pass issubclass(Bar, Foo)
动态导入模块
# 导入模块形式为字符串
import importlib lib = __import__('lib.aa') # 这是解释器自己内部用的
print(lib.aa.C().name) aa = importlib.import_module('lib.aa') # 与上面这句效果一样,官方建议用这个
print(aa.C().name)
异常处理
1、异常基础
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
try:
pass
except Exception,ex:
pass
需求:将用户输入的两个数字相加
while True:
num1 = input('num1:')
num2 = input('num2:')
try:
num1 = int(num1)
num2 = int(num2)
result = num1 + num2
except Exception, e:
print '出现异常,信息如下:'
print e
2、异常种类
python中的异常种类非常多,每个异常专门用于处理某一项异常!!!
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
常用异常
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
更多异常
dic = ["wupeiqi", 'alex']
try:
dic[10]
except IndexError, e:
print e
实例:IndexError
dic = {'k1':'v1'}
try:
dic['k20']
except KeyError, e:
print e
实例:KeyError
s1 = 'hello'
try:
int(s1)
except ValueError, e:
print e
实例:ValueError
对于上述实例,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。
# 未捕获到异常,程序直接报错 s1 = 'hello'
try:
int(s1)
except IndexError,e:
print e
所以,写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:
s1 = 'hello'
try:
int(s1)
except IndexError,e:
print e
except KeyError,e:
print e
except ValueError,e:
print e
万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:
s1 = 'hello'
try:
int(s1)
except Exception,e:
print e
接下来你可能要问了,既然有这个万能异常,其他异常是不是就可以忽略了!
答:当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。
s1 = 'hello'
try:
int(s1)
except KeyError,e:
print '键错误'
except IndexError,e:
print '索引错误'
except Exception, e:
print '错误'
3、异常其他结构
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass
4、主动触发异常
try:
raise Exception('错误了。。。')
except Exception,e:
print e
5、自定义异常
class WupeiqiException(Exception): def __init__(self, msg):
self.message = msg def __str__(self):
return self.message try:
raise WupeiqiException('我的异常')
except WupeiqiException,e:
print e
6、断言
# assert 条件 assert 1 == 1 assert 1 == 2
Socket 编程
参考:http://www.cnblogs.com/wupeiqi/articles/5040823.html
作业:开发一个支持多用户在线的FTP程序
要求:
- 用户加密认证
- 允许同时多用户登录
- 每个用户有自己的家目录 ,且只能访问自己的家目录
- 对用户进行磁盘配额,每个用户的可用空间不同
- 允许用户在ftp server上随意切换目录
- 允许用户查看当前目录下文件
- 允许上传和下载文件,保证文件一致性
- 文件传输过程中显示进度条
- 附加功能:支持文件的断点续传
python重拾第七天-面向对象进阶的更多相关文章
- python自动化开发-[第七天]-面向对象
今日概要: 1.继承 2.封装 3.多态与多态性 4.反射 5.绑定方法和非绑定方法 一.新式类和经典类的区别 大前提: 1.只有在python2中才分新式类和经典类,python3中统一都是新式类 ...
- python学习笔记-(十一)面向对象进阶&异常处理
上篇我们已经了解了一些面向对象的基础知识,本次就了解下面向对象的一些进阶知识(虽然我也不知道有什么卵用). 静态方法 静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作.使 ...
- python 自动化之路 day 08 面向对象进阶
面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 面向对象高级语法部分 经典类vs新式类 把下面代码用python2 和python3都执行一下 1 2 ...
- Python开发基础-Day22反射、面向对象进阶
isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象,如果是返回True class Foo ...
- Py修行路 python基础 (十九)面向对象进阶(下)
item系列 __slots__方法 __next__ 和 __iter__实现迭代器 析构函数 上下文管理协议 元类一.item系列 把对象操作属性模拟成字典的格式. 例如:对象名['key'] ...
- 第七天 面向对象进阶与socket编程
1.静态方法(用得少)(解除某个函数跟类的关联,加了静态方法后,类便不能将类的参数传给静态方法函数了) class Dog(object): def __init__(self,name): @sta ...
- python成长之路七-函数的进阶
1,python中,名称空间分三种: 全局命名空间 局部命名空间(临时命名空间) 内置名称空间 2,作用域(两种): 1,全局作用域 包含:全局名称空间 内置名称空间 2,局部作用域 包含:局 ...
- Python之路(第二十七篇) 面向对象进阶:内置方法、描述符
一.__call__ 对象后面加括号,触发执行类下面的__call__方法. 创建对象时,对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()( ...
- python's twenty-third day for me 面向对象进阶
普通方法:对象和类绑定的过程. class A: def func1(self):pass def func2(self):pass def func3(self):pass def func4(se ...
- python3.x 基础七:面向对象进阶
类的高级方法: 1.静态方法:在类方法前增加关键字@staticmethod,将普通方法变成静态方法,不能再次传值,不能访问实例变量或者类变量,与类的关系仅仅是通过类名进行调用 2.类方法:在类方法前 ...
随机推荐
- Petalinux 基本工程的构建
Petalinux 基本工程的构建 在上一节,我们安装好linux了,这一节,我们搭建一个简单的工程测试一下,并通过TF卡启动 电脑环境 vivado版本:2019.2 petalinux版本:201 ...
- OLAP系列之分析型数据库clickhouse单机版部署(一)
一.概述 官网:https://clickhouse.com/docs/zh ClickHouse是Yandex于2016年开源的列式存储数据库(DBMS),主要用于在线分析处理查询(OLAP),能够 ...
- 移动端、微信小程序兼容性问题汇总(持续更新……
1. safari浏览器字体不能自动随网页缩放调整大小 -webkit-text-size-adjust:100% 2. 点击<button><input>有灰色透明背景 -w ...
- 【人脸识别】OpenCV获取自己的图像
思路:先获取10000张自己的图像,然后通过CNN神经网络进行学习. 第一步:先获取自己的脸的数据.如何做? 代码如下: import cv2 import os import sys import ...
- golang向上取整、向下取整和四舍五入
一.概述 官方的math 包中提供了取整的方法,向上取整math.Ceil() ,向下取整math.Floor() 二.用法 package main import ( "fmt" ...
- angular 获取DOM元素 多种方式
第一种方式 ---ViewChild <div #box>我是div----添加在html页面中</div> @ViewChild('box') box: ElementRef ...
- Python基础篇(数据类型)
str(字符串) Python中最常用的数据类型就是字符串,其用途也很多,我们可以使用单引号 ''或者双引号""来创建字符串.字符串是不可修改的.关于字符我们从 创建.索引.切片. ...
- TypeScript入门介绍
目录 TypeScript入门介绍 什么是 TypeScript? 发展历史 优缺点 应用场景 开发工具 环境依赖 编程IDE vs调试 构建工具/工程化 步骤汇总 第一个项目 TypeScript入 ...
- 推荐一款模拟浏览器自动化操作神器!Mechanize
大家好,我是狂师! 今天给大家推荐一款用于模拟浏览器行为以进行网页自动化操作Python库:Mechanize. 1.介绍 Mechanize是Python中的一个库,它被设计用来自动化网页浏览和数据 ...
- web component基础概念及使用
概念和使用 作为开发者,我们都知道尽可能多的重用代码是一个好主意.这对于自定义标记结构来说通常不是那么容易 - 想想复杂的HTML(以及相关的样式和脚本),有时您不得不写代码来呈现自定义UI控件,并且 ...