Python全栈开发之7、面向对象编程进阶-类属性和方法、异常处理和反射

一、类的属性

1、@property属性

作用就是通过@property把一个方法变成一个静态属性

class Room:

    def __init__(self,name,length,width,height):
self.name=name
self.length=length
self.width=width
self.height=height @property
def cal_area(self): return self.length*self.width r1=Room("room1",100,100,100)
print(r1.cal_area)
class Flight(object):
def __init__(self,name):
self.name=name def checking_status(self): print("checking flight %s status"%self.name) return 1 @property
def flight_status(self): status=self.checking_status()
if status==0:
print("flight has canceled")
elif status==1:
print("flight has arrived")
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)) f=Flight("东方航空") f.flight_status
f.flight_status=2

示例

二、类的方法

1、类方法@classmethod

供类使用的方法,类级别调用

class Room:
tag="一居室"
def __init__(self,name,length,width,height):
self.name=name
self.length=length
self.width=width
self.height=height @classmethod
def roomInfo(cls): #cls是自动生成的,类方法只能访问类变量,不能访问实例变量
print(cls.tag) Room.roomInfo() #通过类直接调用

2、静态方法 @staticmethod

通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法.

普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

class Dog(object):

    def __init__(self,name):
self.name=name @staticmethod # 静态方法跟类没什么关系 相当于普通函数
def eat(name,food): # 把eat方法变为静态方法
print("%s is eating %s"%(name,food)) Dog.eat('alex',"面包")
class Dog(object):

    def __init__(self,name):
self.name=name @staticmethod #静态方法跟类没什么关系 相当于普通函数
def eat(self): #把eat方法变为静态方法 print("%s is eating food"%self.name) d=Dog("xiaoming")
d.eat() #这样调用会报错

报错如下:说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

Traceback (most recent call last):
File "D:/python/day7/静态方法.py", line 23, in <module>
d.eat()
TypeError: eat() missing 1 required positional argument: 'self'

想让上面的代码可以正常工作有两种办法

1. 调用时主动传递实例本身给eat方法,即d.eat(d)

class Dog(object):

    def __init__(self,name):
self.name=name @staticmethod
def eat(self): print("%s is eating food"%self.name) d=Dog("xiaoming")
d.eat(d) #这样调用 或者Dog.eat(d)
在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了

三、isinstance(obj,cls)和issubclass(sub,super)

class Foo:
pass f1=Foo() #判断一个对象是否是一个类的实例
print(isinstance(f1,Foo))
# 返回 True

isinstance(obj,cls)判断一个对象是否是一个类的实例

class Foo:
pass class Bar(Foo):
pass # 判断一个类是否是另一个类的子类
print(issubclass(Bar,Foo))
# 返回 True

issubclass(sub,super)判断一个类是否是另一个类的子类

四、类的特殊成员方法

1.__doc__ 方法

class Foo:
""" 描述类信息 """ def func(self):
pass print (Foo.__doc__)
#输出:描述类信息

__doc__方法:类的文档描述信息

2.__module__ 和  __class__  

__module__ 表示当前操作的对象在那个模块

__class__     表示当前操作的对象的类是什么

3. __init__ 构造方法,通过类创建对象时,自动触发执行

4. __del__  : 析构方法,当对象在内存中被释放时,自动触发执行

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,

所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

5. __call__ 方法 : 对象后面加括号,触发执行

class Dog(object):

    def __init__(self, name):
self.name = name def __call__(self, *args, **kwargs):
print(args, kwargs) d = Dog("Jim") d() # 对象加括号() 就执行__call__方法

__call__()方法

6.  __dict__ 查看类或对象中的所有成员 

7.  __str__  :如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值

class Dog(object):

    name='jim'

    def __init__(self,name):
self.name=name def __str__(self): return "__str_" d=Dog("Jim") print(d) #打印对象时 输出__str__方法的返回值而非内存地址

__str__()方法

 6. __new__和 __metaclass__方法

class Foo(object):

    def __init__(self,name):
self.name=name def __str__(self): return self.name f=Foo("xiaoming") print(f)
print(type(f))
print(type(Foo)) #Foo()类也是由type类实例化产生 输出:
xiaoming
<class '__main__.Foo'>
<class 'type'>

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

五、反射

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

1、hasattr()方法

hasattr(object, name)  判断object中有没有一个name字符串对应的方法或属性

2、getattr()方法

getattr(object, name, default=None)  去object对象中获取name成员内存地址

3、setattr()方法

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''
"""
pass
#   setattr是给一个对象添加一个新的属性或方法

4、delattr()方法

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''
"""
pass
def talk(self):
print("%s is talking"%self.name) class Dog(object):
def __init__(self,name):
self.name=name def eat(self): print("%s is eating .."%self.name) d=Dog("哈巴狗") choice=input(">>:").strip()
#
# print(hasattr(d,choice)) #反射 hasattr 判断一个对象里是否有对应的字符串的属性方法映射
#
# print(getattr(d,choice)) #相当于print(d.eat) 得到eat的内存地址
#
# func=getattr(d,choice) #根据字符串去获取obj对象里的对应的方法的内存地址,没有就会报错
# func() setattr(d,'age',18) # 给对象设置一个属性
print(d.__dict__) # 查看d的属性 setattr(d,choice,talk) #设置一个函数属性,相当于d.choice=talk 把talk的内存地址赋给了对象d.choice
setattr(d,"func1",lambda x:x+1) func=getattr(d,choice)
print(d.__dict__)
func(d) delattr(d,choice) # 删除属性

示例

5、__getattr__()方法和__getattrbute__()方法

class FileHander:

    def __init__(self,filename,mode='r',encoding="utf-8"):
print(mode)
self.file=open(filename,mode=mode,encoding=encoding) def __getattr__(self, item): return getattr(self.file,item) f1=FileHander("a.txt",'a+') f1.write("")
f1.seek(0)
data=f1.read() print(data)

__getattr__()没有属性就会调用该方法

class Foo:
def __init__(self,age): self.age=age def __getattr__(self, item): print("执行的是getattr") def __getattribute__(self, item):
print("执行的是getattrbute") f1=Foo(18)
print(f1.name) # 访问不存在的属性,如果没有__getattrbute__()方法,会触发__getattr__()方法
print(f1.age) # 否则有或者没有该属性都会触发__getattrbute__()方法

__getattrbute__()方法

6、__getitem__()和__setitem__()、__delitem__()方法

class Foo:

    def __init__(self,age):
self.age=age def __getitem__(self, item): print("get item")
return self.__dict__[item]
def __setitem__(self, key, value): self.__dict__[key]=value
print("set item") def __delitem__(self, key):
self.__dict__.pop(key)
print("del item") f1=Foo(18) f1['name']="allen" print(f1.__dict__) print(f1['name'])
print(f1.name)
print(f1['age'])
del f1['name']

方法示例--中括号方式操作属性

7、__format__()方法

date_format_dict={'ymd':"{0.year}-{0.month}-{0.day}",
'm-d-y':"{0.month}-{0.year}-{0.day}",
'y:m:d':"{0.year}:{0.month}:{0.day}"} class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day def __format__(self, format_spec): if not format_spec or format_spec not in date_format_dict:
format_spec="ymd"
fm=date_format_dict[format_spec]
return fm.format(self) d=Date(2019,11,18) # x="{0.year}-{0.month}-{0.day}".format(d)
# print(x) print(format(d))
print(format(d,'y:m:d'))

__format__(self, format_spec)方法

六、异常处理

在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是显示一个提示的页面,通俗来说就是不让用户看见大黄页!!!

names=['jim','lucy']
data={}
print(type(data))
s1='hello' try: #异常处理
#open('t.txt')
# data['name']
int(s1)
names[2] # except IndexError as e :
# print("no names[2]",e)
#
# except KeyError as k:
# print("key error",k) except ValueError as e: #python3 用as python2.6 用
print(e) except Exception as e: #抓住所有异常错误
print("出错了",e) else:
print("一切正常") finally:
print("不管有没有错,都执行")

 python3 用as python2.6 用 ,      except ValueError , e:

异常种类

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

在python的异常中,有一个万能异常:Exception,他可以捕获任意异常

自定义异常

class TestExceptipon(Exception):
def __init__(self,msg):
self.msg=msg def __str__(self): return 'asdasd' try:
raise TestExceptipon('我的异常') #触发自己写的异常 except TestExceptipon as e:
print(e)

动态导入模块

import importlib   #动态导入模块

aa=importlib.import_module("lib.aa")    #aa为lib文件下的一个模块

#复制给aa

aa.test()  调aa模块里面的test()函数  

print(aa.name)

assert断言

import importlib

lib=importlib.import_module("lib.aa")

lib.test()

print(lib.name)

assert type(lib.name) is str   #断言lib.name是一个字符串就往下执行

print('ok')

print("okkk")
上一篇:python装饰器、继承、元类、mixin,四种給类动态添加类属性和方法的方式(一)


下一篇:如果解决小程序1024kb渲染之坑