zoukankan      html  css  js  c++  java
  • python3之类和对象

    一、面对对象(OOP)的三大特征

    1 多态

    无需知道对象是什么类型就能对它执行操作
    不同类型的对象执行相同的操作,操作结果随着对象的类型而异
    多态是方法的多态,属性没有多态

    示例

    def add(x,y):
        return x+y
    
    sum1=add(2,3)
    sum2=add('aaa','bbb')
    print(sum1)
    print(sum2)
    
    数值返回两数字的和,字符串返回两个字符串拼接后字符串

    2 封装

    将对象的状态信息隐藏在对象内部,只对外提供必要的方法,不允许外部直接访问对象内部信息
    向外部隐藏不必要的细节
    无需知道对象的构造就能对它执行操作
    通过私有属性、私有方法的方式实现封装,即属性、方法前面加上双下划线("__")

    3 继承

    创建一个与已有类相似的类,但是比原有类多了一些方法
    新创建的类被称为子类(派生类),原有的类被称为父类(基类、超类)
    子类可以继承父类,一个子类可以有多个父类

    二、面对对象(OOP)术语简介

    类(Class)
    具有相同的属性或方法的对象的集合
    定义了该集合中每个对象所共有的属性和方法
    
    属性
    类中定义的所有变量和方法,包括类变量和方法,实例变量
    
    数据成员
    类变量或者实例变量,用于处理类及其实例对象的相关的数据
    
    类变量
    类的所有实例共享的属性,可以通过"类名.变量名"直接访问
    类变量通常不作为实例变量使用
    
    
    方法
    类中定义的函数
    
    类对象
    通过类定义的数据结构实例
    支持两种操作:属性引用和实例化
    
    属性引用(对属性点号运算)
    obj.属性名
    
    
    实例对象
    类实例化之后,类的具体实例对象
    
    实例变量
    实例化之后,每个实例单独拥有的变量
    只作用于当前实例
    以"self."开头,仅供各个实例对象调用
    
    实例方法
    实例化之后,每个实例都可以调用的方法
    至少包含一个参数,第一个参数约定俗成命名为"self",通过它来传递实例的属性
    
    方法重写
    如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写

    示例

    class Bird:
        #类变量
        n = 999
        
        #实例方法
        def walk(self, name):
            print(name,'正在行走')
        
        #类方法
        @classmethod
        def fly (cls, name):
            print('类方法fly:',cls)
            print(name,'正在飞')
    
    #类实例化,返回一个Bird对象,并赋值给变量u       
    u = Bird()
    #传入实例变量name的值
    u.walk('monkey')
    #通过实例对象调用类变量
    print(u.n)
    #通过类名调用类变量
    print(Bird.n)
    #通过类名调用类方法
    Bird.fly('butterfly')
    
    
    
    class Person:
        hair='black'
        
        def set_name(self,name):
            self.name=name
            
        def get_name(self):
            return self.name
            
        def greet(self):
            print("hello,world!I'm %s" % (self.name))
    
    #直接调用类变量
    print(Person.hair)
    #类实例化,返回一个Persoon对象,并赋值给变量person
    person = Person()
    #通过实例调用类变量
    print(person.hair)
    #调用实例方法并传入实例变量name的值
    person.set_name('marry')
    #调用实例变量
    print(person.name)
    #调用实例方法
    print(person.get_name())
    #调用实例方法
    person.greet()

    三、类定义

    格式

    class class_name:
        <statement-1>
        .
        .
        .
        <statement-N>

    四、方法

    1 实例方法

    类中定义的方法默认是实例方法,和定义普通函数方法一致,但实例方法至少包含一个参数(通常是self),self参数会自动绑定调用者,指向调用者本身
    调用实例方法时不需要为self参数传入值

    示例

    class Person:
        def set_name(self, name):    
            self.name=name
            
        def get_name(self):
            return self.name
            
        def greet(self):
            print("hello,world!I'm %s" % (self.name))
    
    
    #类实例化
    person = Person()
    #调用实例方法并传入实例变量name的值,第一个参数self会自动绑定到调用者
    person.set_name('marry')
    #调用实例变量
    print(person.name)
    #调用实例方法
    print(person.get_name())
    #调用实例方法
    person.greet()

    2 类方法

    使用@classmethod修饰的方法
    类方法的cls参数会自动绑定类,执行该类
    可以通过实例对象调用也可以通过类对象直接调用
    调用类方法时不需要为cls传入参数

    示例

    class test:
        @classmethod
        def class_method(cls):
            print('类方法:',cls)
            
        @classmethod
        def classm(cls,name):
            print('类方法:',cls)
            print(name)
    
    #类实例化
    T = test()
    #通过实例对象调用类方法,只有cls一个参数,指向test类,调用时不需要传入值
    T.class_method()
    #该方法有两个参数,第一个cls指向test类,第二个参数需要调用时需要传入值
    T.classm('jack')
    #通过类名调用类方法
    test.class_method()
    test.classm('marry')

    3 静态方法

    使用@staticmethod修饰的方法
    可以通过实例对象调用也可以通过类对象直接调用
    调用时,需要传入参数,不会自动绑定

    示例

    class static:
        @staticmethod
        def static_method(p):
            print('静态方法:',p)
    
    #类实例化
    S = static()
    #通过实例对象调用类方法,必须传入参数值
    S.static_method('message')
    #通过类对象直接调用,必须传入参数值
    static.static_method('info')

    五、类内置方法

    定义类时,前后都有双下划线定义的方法,都属于类的特殊方法
    可以重写或者直接调用这些方法来实现特殊的功能

    1 __init__(self) 方法

    初始化方法(构造方法)
    用于初始化实例化对象属性值
    创建类的实例时就会调用该方法
    若该方法有多个参数时,类实例化必须要传入参数

    示例

    class Rectangle():
        def __init__(self, length, width):
            self.length = length
            self.width = width
            
        def getPeri(self):
            return ((self.length + self.width) * 2)
            
        def getArea(self):
            return (self.length * self.width)
    
    #类中定义了__init__方法且该方法不止一个参数,实例化时必须要传入length,width两个参数
    R = Rectangle(6,5)
    print(R.getPeri())
    print(R.getArea())

    2 __str__(self) 和 __repr__(self) 方法

    如果两个方法都定义了,print() 方法会调用  __str__  方法
    如果只想调用 __repr__ ,只需定义 __repr__ 方法
    如果两个方法都没有定义,print()使用object基类中默认的 __str__ 方法,因为object是所有类的基类
    __repr__ 和 __str__ 这两个方法都是用于显示的, __str__ 是面向用户的,而 __repr__ 面向程序员

    只能输出字符串类型数据
    使用中推荐至少有一个 __repr__ 方法

    示例

    class Repr:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    class Repr1:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        #重新定义__str__方法
        def __str__(self):
            return 'this is __str__'+'		'+self.name+":"+str(self.age)
    
        #重新定义__repr__方法
        def __repr__(self):
            return 'this is __repr__'+'		'+self.name+":"+str(self.age)
    
    class Repr2:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        #重新定义__repr__方法
        def __repr__(self):
            return f'this is __repr__,    {self.name}:{self.age}'
    
         
    R = Repr('mack',22)
    #未定义__str__和__repr__方法,print(R)使用object基类中的默认__str__方法
    print(R)
    print(R.__repr__)
    print(R.__str__)
    print()
    print()
    print()
    
    R1 = Repr1('jack',20)
    #调用__str__方法输出
    print(R1)
    print(R1.__repr__)
    print(R1.__str__)
    print()
    print()
    print()
    
    R2 = Repr2('maryy',18)
    #调用__repr__方法输出
    print(R2)

    3 __del__(self) 方法

    对象引用计数为0时,对象才会被回收,自动调用 __del__ 方法
    即一个对象被多个变量引用时,del删除该对象时不会立即回收对象

    一般出现在两个地方:
    1、手动减少对象引用计数至0,被垃圾回收处理时调用
    2、程序结束时调用

    示例

    class Del:
        def __init__(self, name, age):
            self.name = name
            self.age = age
            
        def __del__(self):
            print("%s对象已被删除" % self)
    
    D_1 = Del('maryy', 22)
    #变量D_2也指向对象
    D_2 = D_1
    #对象不会被回收,程序执行完才会调用__del__方法
    del D_1
    print(D_2.name,D_2.age)
    class Del:
        def __init__(self, name, age):
            self.name = name
            self.age = age
            
        def __del__(self):
            print("%s对象已被删除" % self)
    
    D = Del('maryy', 22)
    #对象立即被回收,调用__del__方法
    del D
    print("是否回收对象")

    4 __dir__(self) 方法

    返回对象内部所有的变量名和方法名组成的列表

    dir(object)返回对象的 __dir__ 方法经过排序后的列表

    示例

    class Dir:
        var1 = 'value1'
        var2 = 'value2'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
            
        def __repr__(self):
            return self.name+' '+str(self.age)
            
        def __del__(self):
            print("删除对象")
    
    
    D = Dir('maryy', 22)  
    #通过实例化对象调用__dir__方法,返回类中所有实例属性组成的列表    
    print(D.__dir__())
    #返回实例化对象调用__dir__方法经过排序后的列表
    print(dir(D))

    5 __dict__(self) 方法

    返回对象内部的所有属性名和属性值组成的字典,该方法可以通过字典的语法来访问或修改指定属性的值

    通过类名调用 __dict__ 方法,输出类中所有的属性,包括类属性,实例属性
    通过实例化对象调用 __dict__ 方法,输出类中所有实例属性组成的字典

    示例

    class Dict:
        var1 = 'value1'
        var2 = 'value2'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __repr__(self):
            return self.name,self.age
    
    #通过类名调用__dict__方法,返回类中所有的属性组成的字典
    print(Dict.__dict__)
    #类实例化
    D = Dict('jack', 24)
    #通过实例化对象调用__dict__方法,返回类中所有实例属性组成的字典
    print(D.__dict__)
    #以字典的语法调用__dict__方法访问属性值
    print(D.__dict__['name'])
    print(D.__dict__['age'])
    #以字典的语法调用__dcit__方法修改属性值
    D.__dict__['name'] = 'tom'
    D.__dict__['age'] = 25
    print(D.__dict__['name'])
    print(D.__dict__['age'])

    6 __getattr__(self) 、__setattr__(self) 、__delattr__(self) 方法

    当对类和该类的所有父类(若有多层继承,沿着继承关系直到最后的基类)中未定义的属性(包括变量和方法)进行点号运算时,调用 __getattr__ 方法
    如果可以找到该属性,则不调用此方法
    仅在引用属性且属性不存在的时候才会触发 __getattr__ 方法
    
    
    只要对属性(不管该属性是否在类中定义)赋值时都会调用 __setattr__ 方法
    当在 __setattr__ 方法内对属性进行赋值时,不可使用self.attr=value,因为会再次调用 __setattr__ 方法,形成无限递归,导致堆栈溢出异常
    一般在 __setattr__ 方法内对属性赋值,使用self.__dict__[attr]=value
    
    删除属性时会调用 __delattr__ 方法

    示例

    class Set:
        def __init__(self,length,width):
            self.length = length
            self.width = width
        
        #重新定义__setattr__方法
        def __setattr__(self,attr,value):
            print('---设置对象属性---')
            #传入的attr参数名是否为size,若是,则重新设置length,width的值
            #否则新增一个名=attr,值=value的变量
            if attr == 'size':
                self.__dict__['length'],self.__dict__['width'] = value
            else:
                self.__dict__[attr] = value
       
        #重新定义__getattr__方法
        def __getattr__(self,attr):
            print('---访问对象属性---')
            #传入的attr参数名是否为size,若是,则返回原来length,width的值
            #否则引发AttributeError异常
            if attr == 'size':
                return self.length,self.width
            else:
                raise AttributeError
        
        #重新定义__delattr__方法
        def __delattr__(self,attr):
            print('---删除对象属性---')
            #传入的attr参数名是否为size,若是,则修改length,width的值为0
            #否则什么也不做
            if attr == 'size':
                self.__dict__['length'] = self.__dict__['width']=0
            else:
                pass
    
    #实例化类,调用__init__方法和__setattr__方法
    S = Set(5,6)
    #返回所有实例属性组成的字典
    print(S.__dict__)
    #size属性赋值,调用__setattr__方法
    S.size = 8,9
    print(S.__dict__)
    #删除size属性
    del S.size
    print(S.__dict__)
    #big属性赋值,调用__setattr__方法
    S.big = 1
    print(S.__dict__)

    7 序列相关的特殊方法

    __len__(self)       返回元素的数量
    __getitem__(self)   返回键对应的值
    __setitem__(self)   设置给定键的值
    __delitem__(self)   删除给定键对应的元素

    示例

    #key检查函数
    #key必须是非负整数
    #若key不是int类型,则引发TypeError
    #若0<key<=pow(26,3),则引发IndexError
    def check_key(key):
        if not isinstance(key, int):
            raise TypeError
        if (key<0) or (key >= pow(26,3)):
            raise IndexError
    
    class seq:
        def __init__(self):
            #存储被修改的数据
            self.__chaged = {}
            #存储被删除元素的索引
            self.__deleted = []
        
        #获取元素个数
        def __len__(self):
            print('---返回元素个数---')
            return pow(26,3)
    
        #获取索引对应的元素的值
        def __getitem__(self, key):
            print('---获取key=%s对应元素的值---'% (key))
            #调用key检查函数
            check_key(key)
            #如果在self.__chaged找到数据,则返回已修改的值
            if key in self.__chaged:
                return self.__chaged[key]
            #如果在self.__deleted中找到数据,说明元素被删除,返回None
            elif key in self.__deleted:
                return None
            #否则,根据计算规则返回元素,得到一个AAA,AAB,AAC,AAD,...,的序列
            else:
                three = key//(pow(26,2))
                two = (key-three*pow(26,2))//26
                one = key%26
                return chr(65+three)+chr(65+two)+chr(65+one)
    
        #设置索引对应元素的值
        def __setitem__(self, key, value):
            print('---设置key=%s对应元素的值---'% (key))
            #调用key检查函数
            check_key(key)
            self.__chaged[key] = value
    
        #删除索引对应元素的值
        def __delitem__(self, key):
            print('---删除序列key=%s对应元素的值---'% (key))
            #调用key检查函数
            check_key(key)
            #如果在self.__deleted中未找到key,则添加该key到删除列表中
            if key not in self.__deleted:
                self.__deleted.append(key)
            #如果在self.__chaged中找到key,则删除该key
            if key in self.__chaged:
                del self.__chaged[key]
    
    
    #得到一个AAA,AAB,AAC,AAD,...,元素个数为pow(26,3)的序列
    Seq = seq()
    
    #获取元素,调用__len__方法
    print(len(Seq))
    
    #获取key=1元素的值,调用__getitem__方法
    print(Seq[1])
    #删除key=1元素的值,调用__delitem__方法
    del Seq[1]
    #获取key=1元素被删除后的值,调用__getitem__方法
    print(Seq[1])
    
    #获取key=2元素的值,调用__getitem__方法
    print(Seq[2])
    #修改key=2元素的值,调用__setitem__方法
    Seq[2] = 'asd'
    #获取key=2元素被修改后的值,调用__getitem__方法
    print(Seq[2])
    class ArithemeticSequence:
        def __init__(self,start,step):
            self.start=start
            self.step=step
            self.myData={}
        
        #定义获取元素个数的方法
        def __len__(self):
            print('---返回元素个数---')
            return len(self.myData)
       
       #定义获取值的方法
        def __getitem__(self,key):
            print('---获取key=%s对应元素的值---'% (key))
            try:
                return self.myData[key]
            except KeyError:
               return self.start+key*self.step
        
        #定义修改元素的方法
        def __setitem__(self,key,value):
            print('---设置key=%s对应元素的值---'% (key))
            self.myData[key]=value
        
        #定义删除元素的方法
        def __delitem__(self, key):
            print('---删除序列key=%s对应元素的值---'% (key))
            del self.myData[key]
    
    #得到一个等差序列实例对象     
    s=ArithemeticSequence(1,2)
    #获取元素个数,初始状态0个元素
    print(len(s))
    #获取key=3元素的值
    print(s[3])
    #修改key=3元素的值
    s[3]=100
    #获取key=3元素被修改后的值
    print(s[3])
    #获取元素个数,只有一个元素
    print(len(s))
    #删除key=3元素的值
    del s[3]
    #获取元素个数,0个元素
    print(len(s))

     六、类继承

    格式

    class SubClass(SuperClass1,SuperClass2,..):
         <statement-1>
        .
        .
        .
        <statement-N> 
    
    
    其中
    SubClass是子类,SuperClass1,SuperClass2,..是父类(基类|超类),多个父类以逗号隔开
    若多个父类中有相同的属性,则使用(SuperClass1,SuperClass2,..)中排在最前面的父类的属性,所以不是很有必要,尽量不使用继承多个父类
    object是所有类的直接父类或间接父类

    示例

    class Fruit:
        def info(self):
            print('水果:%s,重量:%s'%(self.name,self.weight))
            
    class Food:
        def taest(self):
            print('不同食物口感不同')
            
    class Apple(Fruit,Food):
        def __init__(self,name,weight):
            self.name=name
            self.weight=weight
    
    A=Apple('apple',5)
    A.info()
    A.taest()

    1 重写父类方法

    示例

    class Father(object):
        def __init__(self, name):
            self.name = name
            print('父类__init__方法')
            
        def getName(self):
            print('父类getName方法')
            return 'Father '+self.name
     
    class Son(Father):
        #重写父类中的getName方法,父类的getName方法被覆盖
        def getName(self):
            print('子类getName方法')
            return 'Son name: '+self.name
     
    son = Son('test_class')
    print(son.getName())
    class Father(object):
        def __init__(self, name):
            self.name = name
            print('父类__init__方法')
            
        def getName(self):
            print('父类getName方法')
            return 'Father name:'+self.name
     
    class Son(Father):
        #重写父类的 __init__ 方法,父类中的 __init__ 方法会被覆盖
        def __init__(self, name):        
            self.name = name
            print('子类__init__方法')
            
        #重写父类中的 getName 方法,父类的 getName 方法被覆盖
        def getName(self):
            print('子类getName方法')
            return 'Son name:'+self.name
     
    son = Son('test_class')
    print(son.getName())

    2 子类中调用父类方法

    格式

    父类名.方法名(参数)
    参数必须和父类方法中参数一致,包括self参数

    示例

    class Father(object):
        def __init__(self, name):
            self.name = name
            print('父类__init__方法')
            
        def getName(self):
            print('父类getName方法')
            return 'Father name:'+self.name
     
    class Son(Father):
        #重写父类中的getName方法
        def getName(self):
            print('子类getName方法')
            #调用父类方法
            print(Father.getName(self))
            return 'Son name:'+self.name
     
    son = Son('test_class')
    print(son.getName())

    3 使用super()函数继承父类的 __init__(self) 方法

    格式

    super().__init__(self): 参数包括父类方法中除了self参数的所有参数

    示例

    class Father(object):
        def __init__(self, name):
            self.name = name
            print('父类__init__方法')
            
        def getName(self):
            print('父类getName方法')
            return 'Father name: '+self.name
     
    class Son(Father):
        def __init__(self, name):
            #继承父类中的__init__方法
            super().__init__(name)
            print('子类__init__方法')
            
        def getName(self):
            print('子类getName方法')
            #子类方法中调用父类方法
            print(Father.getName(self))
            return 'Son name: '+self.name
     
    son = Son('test_class')
    print(son.getName())

    七、枚举类

    类的对象有限而且固定,例如季节,星期几
    枚举类不能用来实例化,且一旦定义创建,不能在外部修改成员值
    可以使用==或者is比较成员,并且可以迭代枚举

    包括

    enum.Enum
    创建枚举常量的基类,value为任意数据类型
    
    enum.IntEnum
    创建枚举常量的基类,value只能是整型数字
    
    enum.IntFlag
    创建枚举常量的基类,value只能是整型数字
    使用按位运算符对其进行组合而不会丢失其IntFlag成员资格
    
    enum.Flag
    创建枚举常量的基类,value为任意数据类型
    使用按位运算符对其进行组合而不会丢失其IntFlag成员资格
    
    enum.unique()
    name不能相同,value也不相同
    
    enum.auto
    成员值随机生成,初始值1

    示例

    from enum import Enum, IntEnum, unique
    
    #枚举类的装饰器,若有value相同则引发ValueError错误并附带相关细节信息
    @unique
    class Season(Enum):
        SPRING = "春天"
        SUMNNER = '夏天'
        FALL = '秋天'
        WINTER = '冬天'
    
    @unique
    class color(IntEnum):
        red = 1
        yellow = 2
        green = 3
        pink = 4
    
    class color2(IntEnum):
        red = 1
        beown = 1
        yellow = 2
        green = 3
        ping = 4
    
    #获取Season枚举类成员SPRING的值
    print(Season.SPRING.value)
    #获取成员的name
    print(Season.SPRING.name)
    #通过成员value获取成员的name
    print(Season('春天'))
    #获取成员name=SPRING的信息
    print(repr(Season.SPRING))
    #获取成员name=SPRING属于哪个枚举类
    print(type(Season.SPRING))
    
    
    menber = Season.SPRING
    #获取成员的name
    print(menber.name)
    #获取成员的value
    print(menber.value)
    
    #枚举类成员比较
    print(Season.SPRING == Season.SPRING)
    print(Season.SPRING is Season.SPRING)
  • 相关阅读:
    腾讯电脑管家创始刘钊:教你如何手撕破解一个木马
    【渗透笔记】拿下复旦大学的艰难过程
    新博客在SEO方面需要注意哪几点?
    【渗透课程】第七篇-上传漏洞之绕过上传漏洞
    【渗透课程】第八篇-上传漏洞之文本编辑器上传
    【渗透课程】第六篇-上传漏洞之解析漏洞
    【渗透课程】第五篇-SQL注入的原理
    【渗透课程】第四篇-Web安全之信息探测
    【渗透课程】第三篇-体验http协议的应用
    三星的高效会议原则
  • 原文地址:https://www.cnblogs.com/gudanaimei/p/13463756.html
Copyright © 2011-2022 走看看