面向对象进阶
Posted ydqq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象进阶相关的知识,希望对你有一定的参考价值。
继承补充:
派生类可以直接使用基类中的方法:
下例中基类有继承,派生类找继承来的bar方法时,可以直接以类D为对象来调用bar方法。
派生类本身是没有bar方法的,他的bar方法是继承基类来的。
bar方法查找过程: D =》 C =》 B =》 A.bar,继承A类中的bar方法,使用的self就变成了D。
class A:
def bar(self):
print("BAR")
self.f1()
class B(A):
def f1(self):
print("B")
class C:
def f1(self):
print("C")
class D(C, B):
pass
d1 = D()
d1.bar()
执行其父类的构造方法
使用super(Cat, slef).init()来调用基类中的函数:
class Annimal:
def __init__(self):
print("A构造方法")
self.ty = "动物"
class Cat(Annimal):
def __init__(self):
print("B构造方法")
self.n = "猫"
super(Cat, self).__init__()
c = Cat()
print(c.__dict__)
通过反射来判断对象里面的成员:
反射,如果操作的对象是个类的话,则只能找类里面的成员
如果操作的是对象,则既可找对象,也可以找类的成员
class Foo:
def __init__(self, name):
self.name = name
def show(self):
print("show")
obj = Foo("xiaoming")
r = hasattr(obj, "name")
print(r)
r = hasattr(obj, "show")
print(r)
r = hasattr(Foo, "name")
print(r)
**方法:**__init__ 查看类里面的所有方法
print(Foo.__dict__)
利用反射查找类中的内容:
#导入模块
m = __import__("s2", fromlist=True)
#去模块中找类
class_name = getattr(m, "Foo")
#根据类创建对象
obj = class_name("xiaoming")
#去对象中找name对应值
val = getattr(obj, "name")
print(val)
面向对象之成员
普通字段:保存在方法中的语句
普通方法:上面类中写的方法都是普通方法
静态字段
将每个对象中同时多次重复的字段,写入类中。以最少的字符,占用最少的内存达成同样作用。
class Provice:
#静态字段
country = "中国"
def __init__(self, name):
temp = "xxx"
#普通字段,对象中
self.name = name
#普通方法,类中
def show(self):
print("shwo")
hebei = Provice("河北")
henan = Provice("河南")
静态方法
@staticmethod:定义方法的语句
静态方法与类方法的不同在于,静态方法没有默认参数self。普通方法,会默认将对象self传入参数。但静态方法没有这个功能。
class Provice:
#静态字段
country = "中国"
def __init__(self, name):
temp = "xxxx"
self.name = name #普通字段,对象中
@staticmethod #定义静态方法用的字符
def xo(arg1, arg2):
print("xo")
#普通方法
def show(self):
print("show")
Provice.xo(1, 2)
类方法:
@classmethod:定义类方法的语句
类方法默认将类名上传到参数中
class Provice:
@classmethod
def xxo(cls): #最少要有个cls参数
print("xxo", cls)
Provice.xxo()
xxo <class '__main__.Provice'>
特性(属性):
@property:定义特性的方法
将普通方法伪装成一个可以访问的字段,调用时可以直接使用调用静态字段的方式使用。
class Provice:
def start(self):
print("ddal")
@property #添加后变成特性
def end(self):
return "daf"
obj = Provice()
ret1 = obj.start()
print(obj.end) #这里直接加 .end使用,不用加括号和参数
(2)设置特性
@setter:设置
class Provice:
@property
def end(self):
temp = "%s da" % self.name
return temp
@end.setter #这里用这个格式,可以给特性配置一个参数
def end(self, value):
print(value)
self.name = value
obj = Provice()
obj.end = "xiaoxiao"
print(obj.end)
总结:
三大特性:封装,继承,多态
规范:
类,对象都可以访问,静态方法,普通方法,静态字段,普通字段。但为了代码一致我们使用下面的规范:
- 通过类访问:静态字段,静态方法,类方法
- 通过对象访问:普通字段,类的方法
成员使用情况:
字段:静态字段(每个对象都有同样数据的情况下使用),普通字段(每个对象的数据都不相同的情况下使用)
方法:静态方法(不需要使用对象内容的情况下使用),类方法(使用常见相似,会把类名传入参数),普通方法(使用对象中数据的情况下)
特性:普通特性(将方法伪装成字段,用对象调用);静态特性()
判断是用类执行还是用对象执行:
有self的用对象调用
没有self的用类调用
成员修饰符
为了起到开放封闭的作用,(__内容)在需要修饰的字段或方法前添加两个下划线来表示成员修饰符。
特性:修饰符不能被在外部调用,也不可以被派生类调用。只能在自己内部调用。
普通字段,普通方法,静态字段和静态方法,如果加上修饰符以后,都不能在外部被直接调用
class Foo:
xo = "xo"
__ox = "ox"
def __init__(self, age, name):
self.age = age
self.__name = name
def fetch(self):
print(self.__name)
obj = Foo("17", "ming") #创建对象并传入参数
print(obj.__name) #直接调用,无法调用
print(Foo.xo) #调用静态字段
print(Foo.__xo) #不可直接调用有修饰符的静态字段
上面这种方法是编程语言中通用的,还有一个Python中特有的修饰符,但应用不广泛。
作用:在外部通过特定格式的调用语句来实现调用
print(obj._Foo__name)
面向对象常用方法
面向对象已知常用方法:
__init__
__del__
__call__ 方法
class Foo:
def __init__(self):
print("init")
def __call__(self, *args, **kwargs):
print("call")
return 1
#Foo() #类名后面加括号,执行__init__方法
r = Foo()() #类后面加两个括号,第一个括号代表执行__init__方法,第二个括号代表执行call方法。并将结果赋值给r
print(r)
方法:
对象.__getitem__
对象.__setitem__
对象.__delitem__
class Foo:
def __init__(self):
self.name = "xiaoming"
def __getitem__(self, item): #对象后面跟中括号执行__getitem__方法
print(item)
def __setitem__(self, key, value): #对象后面跟中括号再跟等号,执行__setitem__方法
print(key, value)
def __delitem__(self, key): #对象后面跟中括号,删除对象中的key并输出删除的内容
print(key)
r = Foo() #创建一个对象
r["abc"] #获取上传上去的对象,执行方法__getitem__
r['abc'] = 123 #像字典一样定义一个key值和value值,并输出。执行方法__setitem__
del r["dadd"] #像字典一样删除一个key值,并输出,执行方法__delitem__
print(r.__dict__) #__dict__ 查看方法里的内容
print(Foo.__dict__) #__dict__查看类中的内容
方法:
类名.__dict__ :以字典的形式获取类里面的内容
class Foo:
def __init__(self):
self.name = "xiaoming"
def __getitem__(self, item):
print(item)
def __setitem__(self, key, value):
print(key, value)
def __delitem__(self, key):
print(key)
print(Foo.__dict__)
执行结果:
'__delitem__': <function Foo.__delitem__ at 0x000000000072C620>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__getitem__': <function Foo.__getitem__ at 0x000000000072C400>, '__init__': <functio......
对象.__iter__ :迭代,for循环对象的时候,自动运行__iter__方法
yield :生成器,生成字符。两个集合起来就表示这个方法可以迭代生成
class Foo:
def __init__(self):
self.name = "xiaoming"
def __iter__(self):
yield 666
yield 888
yield "dalj"
obj = Foo()
for i in obj:
print(i)
异常处理程序
执行时,因为不同的原因造成报错。对这些报错信息加工,这个过程就叫做异常处理。
基本格式:
inp = input("请输入数字:")
try: #如果出错,就捕获错误
num = int(inp)
print(num)
except Exception as e:
print("数据错误", e)
常见错误类型:
AttributeError #试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError #输入/输出异常;基本上是无法打开文件
ImportError #无法引入模块或包;基本上是路径问题或名称错误
IndentationError #语法错误(的子类) ;代码没有正确对齐
IndexError #下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError #试图访问字典里不存在的键
KeyboardInterrupt #Ctrl+C被按下
NameError #使用一个还未被赋予对象的变量
SyntaxError #Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError #传入对象类型与要求的不符合
UnboundLocalError #试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError #传入一个调用者不期望的值,即使值的类型是正确的
例子:
dic = ["xiao", "ming"]
try:
dic[5]
except IndexError as e: #指定错误类型并起一个 别名
print(e)
list index out of range
常见的错误类型只能处理固定的单一错误。如果错误类型不是指定的错误时则会报错。
为了使所有错误类型都可以被显示,就有了万能错误类型:Exception
Exception 能够接收所有的错误类型
dic = ["xiao", "ming"]
try:
dic["xa"]
except IndexError as i:
print(i)
except ValueError as v:
print(v)
except Exception as e:
print(e)
上面的代码,在执行的时候会从上到下依次判断错误类型。
使用指定的错误类型,能够让错误类型输出更加准确。
完整错误异常结构:
dic = ["xiao", "ming"]
try:
dic["xa"]
except IndexError as i:
print("判断错误类型并输出")
else:
print("如果except执行成功则执行")
finally:
print("无论执行成不成功都要执行我")
主动触发异常:raise
代码执行成功则主动触发异常生效,代码错误则按照异常处理来执行,有点没事找事的意思。
dic = ["xiao", "ming"]
try:
dic[1]
raise Exception("出错.....") #上面的代码执行成功,给exception定义一个对象(出错)
except Exception as e: #上一句定义的对象会赋值给e
print(e) #执行这个对象
补充类中的特殊方法:
__str__:如果直接print(对象)的时候,将对象的内容以字符串的形式显示
class dema:
def __init__(self, ma):
self.de = ma
def __str__(self): #使用__str__方法
return self.de #__str__方法要和return结合,可以执行返回对象
obj = dema("lalallalalal")
print(obj) #直接print(对象)就会触发__str__方法,直接以字符串的形式输出对象
断言:assert
指定条件,如果成立则为True,如果不成立则为False。类似与简写的判断
assert 1 == 1 #成立则成功
assert 1 == 2 #不成立则会报错
以上是关于面向对象进阶的主要内容,如果未能解决你的问题,请参考以下文章