python-面向对象,,面向对象编程——Ob


面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

面向对象的设计思想是抽象出Class,根据Class创建Instance
面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

类名通常是大写开头的单词,采用驼峰式

在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可
以通过_Student__name来访问__name变量:
但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名。

在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用
__name__、__score__这样的变量名。

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

python多继承-新式类、经典类

比如父类中有一个run方法,子类也定义了run方法,父类对象.run会调用父类的run,子类对象.run则调用子类的run,这就是多态
一个子类对象的类型既是子类,也是父类,这也是多态

静态语言与动态语言的区别:比如定义一个函数,传入对象,调用对象的run方法
对于静态语言(例如Java)来说,参数设置需要指定类型,传入的对象必须是指定类型或者子类,否则调用失败
而对于动态语言来说,传入的对象没有任何类型的限制,只需要这个对象也有run方法即可
这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

type(obj)表示obj是有谁创建的: 当obj为实例化对象时,结果为类,因为obj是由该类创建的;当obj为类时,结果为type,因为类是有type创建的
isinstance(obj,class)则是判断obj是什么类型:当obj为实例化对象时,结果为类,因为obj的类型是该类; 当obj为类时,结果为object,因为它的类型是object
对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

实例属性属于各个实例所有,互不干扰;
类属性属于类所有,所有实例共享一个属性;
不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。

技术分享图片
类可以起到模板的作用,通过定义一个特殊的__init__方法,在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;class foo:#定义类    staticword = ‘staticword‘#静态字段/类属性,类/对象都可以访问    __nationl = ‘china‘#静态私有字段,可以在类内部用类名.xxxx/对象.xxxx访问,外部访问应该通过方法间接访问    def __init__(self,name,age):#类的构造方法,创建对象时自动执行        self.name = name#定义普通字段/普通变量,通过对象来访问        self.__age = age#私有字段/私有变量,可以在类内部通过对象访问,外部无法直接进行访问        #父类的私有字段,无法继承,子类的方法无法直接调用父类的私有字段    def f1(self):#定义普通方法,对象.xxxx()来访问/类名.f1(对象)也可以访问        print(‘执行普通方法‘)    @staticmethod    def f2():#定义静态方法,类名.xxxx()/对象.xxxx()都可以访问        print(‘执行静态方法‘)    @classmethod    def f3(cls):#定义类方法,类名.xxxx()/对象.xxxx()都可以访问        print(‘执行类方法‘)    @property#不伦不类1    def f4(self):#对象.xxxx直接访问/但类名.xxxx访问不成功,也不报错?        print(‘property‘)        return 1    @f4.setter#不伦不类1    def f5(self,xxx):#对象.f5 = 123(任意数值),此处方法名和定义为f4        print(‘perr.setter‘)    @f4.deleter#不伦不类1    def f6(self):# del 对象.f6,此处方法名和定义为f4        print(‘perr.deleter‘)    def wordtest(self):        print(self.__age)#间接访问私有字段        print(foo.__nationl)#间接访问私有字段        return foo.__nationl#间接访问私有字段    def __call__(self, *args, **kwargs):#对象()/类名()()  自动执行        print(‘__call__‘)    def __int__(self):#int(对象)  自动执行,返回值赋值给int对象        print(‘__int__‘)#貌似并不是赋值给对象,因为进行int(对象)操作之后,单独打印对象,显示的还是‘s`123‘        return 1233#必须为数字,否则报错,    def __str__(self):#str(对象)  自动执行        print(‘__str__‘)#print(对象)也会自动调用对象的str方法        #print(对象) ==print(str(对象))        return ‘s`123‘    def __add__(self, other):#对象+对象   定义了该方法后,进行+时自动执行第一个对象的该方法,把第二个对象当参数传入,返回自定义的值        return self.name+other.name    def __del__(self):#在对象被销毁时,自动执行该方法        print(‘析构方法‘)#没什么用,知道一下    #对象.__dict__  将对象中封装的所有内容通过字典的形式返回    #类名.__dict__  将类中的所有内容通过字典的形式返回,包括一个备注(‘‘‘ ‘‘‘)也会当做类成员,成为一对键值对    def __getitem__(self, item):#对象[9]  自动执行该方法,将9作为参数传递给item        #在python3中,通过类似列表切片的方式 list[1:6:2]还是执行__getitem__;但在python2中不是        if type(item) == slice:            print(‘对象为slice,切片处理‘)            print(item.start,111)            print(item.stop,222)            print(item.step,333)        else:            print(‘对象为非slice,索引处理‘)        # return item+10    def __setitem__(self, key, value):#对象[9] = 123;自动执行该方法,不需要设置return                 self.key=value        print(‘__setitem_____‘)    def __delitem__(self, key):        print(‘delete%s‘%key)#del 对象[9];自动执行该方法,不需要设置return    def __iter__(self):        return iter([1,2,3])    #如果类中有__iter__方法,那么该类产生的对象为---可迭代对象    #对象.__iter__()的返回值:迭代器    #for循环的对象是一个迭代器时,直接执行next    #for循环的对象是一个可迭代对象时,执行对象.__iter__(),返回一个迭代器,再对迭代器执行nextfo = foo(‘allen‘,30)for i in fo:#1、若fo为迭代器,直接进行迭代;2、若fo为可迭代对象,执行__iter__方法,取返回值    print(i,112233)
类属性、方法技术分享图片
class F:    def f1(self):        print(‘111‘)class S(F):#继承F    def f2(self):        print("222")    def f1(self):#若不想继承父类的方法,只需要自己内部也创建一个相应的方法        super(S,self).f1()#若想同时执行父类的同名函数,可以这样        print(‘333‘)#super(S,self)等同于父类        #F.f1()#另一种调用父类方法的写法obj = S()#2个动作,1.创建对象,2.执行__init__进行属性赋值obj.f1()obj.f2()S.f2(obj)#调用方法的另一种写法        面向对象三大特性之一:封装面向对象三大特性之二:继承    1、继承                2、重写        防止执行父类中的方法#修改父类的方法    3、self永远是执行该方法的调用者    4、super(子类, self).父类中的方法(...)       父类名.父类中的方法(self,...)    5、Python中支持多继承#java不能多继承        a. 左侧优先        b. 一条道走到黑        c. 同一个根时,根最后执行面向对象三大特性之三:多态    ====> 原生多态            类成员:    # 字段         - 普通字段,保存在对象中,只能通过对象访问        - 静态字段,保存在类中,  可以通过对象访问;也可以通过类访问            # 方法        - 普通方法,保存在类中,由对象来调用,self=》对象        - 静态方法,保存在类中,由类直接调用        -   类方法,保存在类中,由类直接调用,cls=》当前类    # 属性,特性        - 不伦不类
笔记

python-面向对象

评论关闭