面向对象进阶

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)

总结:

三大特性:封装,继承,多态

规范:
类,对象都可以访问,静态方法,普通方法,静态字段,普通字段。但为了代码一致我们使用下面的规范:

  1. 通过类访问:静态字段,静态方法,类方法
  2. 通过对象访问:普通字段,类的方法

成员使用情况:
字段:静态字段(每个对象都有同样数据的情况下使用),普通字段(每个对象的数据都不相同的情况下使用)

方法:静态方法(不需要使用对象内容的情况下使用),类方法(使用常见相似,会把类名传入参数),普通方法(使用对象中数据的情况下)

特性:普通特性(将方法伪装成字段,用对象调用);静态特性()

判断是用类执行还是用对象执行:
有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    #不成立则会报错

以上是关于面向对象进阶的主要内容,如果未能解决你的问题,请参考以下文章

Java-进阶篇面向对象进阶

Python基础-第七天-面向对象编程进阶和Socket编程简介

面向对象进阶小结

Python - - 面向对象 - - 面向对象进阶

面向对象进阶

python进阶之面向对象初识