python-面向对象

Posted allenwoo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-面向对象相关的知识,希望对你有一定的参考价值。

面向对象编程——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__(),返回一个迭代器,再对迭代器执行next

fo = 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-面向对象的主要内容,如果未能解决你的问题,请参考以下文章

python之路之前没搞明白4面向对象(封装)

Python面向对象学习之八,装饰器

python:第二部分:面向对象:面向对象object orinted

面向面试编程代码片段之GC

Python 面向对象

面向对象编程其实很简单——Python 面向对象(初级篇)