• python 基础(十) 面向对象


    面向对象

    一、概念

    1. 类(class): 用来描述具有相同属性和方法的对象的集合 对象是类的实例化

    2. 类变量:类变量在整个实例化的对象中是共用的。定义在类中 并且是函数体外的

    3. 实例变量:只能作用于 当前类的实例化后的某一个对象上

    4. 实例: 创建一个类的具体实例 类的具体化对象

    5. 方法: 就是类中的函数

    6. 属性:就是类中的函数外的变量

    二、命名方式

    1. 大驼峰 首字母大写

    2. 见名知意

    3. 严格区分大小写

    三、类的定义

    class 类名:

    ​ 属性

    ​ 方法

    其中的属性 和方法 都是可有可无(语法上没有问题的)

    四、类中的属性和方法的调用

    对象 = 类名([参数])

    对象.属性名

    对象.方法名([参数])

    五、self

    self代表当前类的实例 而非类

    在你实例化类的时候 会自动传入 方法需要有一个参数来去接收当前实例化后的的对象 这个self对象 就是外部实例化的那个对象

    self的作用:

    1. 可以去创建对象属性

    2. 在类的内部调用属性和方法 和外部一样 对象.属性/方法名 只是里面的对象 统一叫self(别的名称也可以 不规范)

    证明

     
    class Person:
        sex = '男'
        def mouth(self,*args,**kwargs):
            print(args,kwargs)
        def test(abc):
            print(abc)
    p1 = Person()
    p2 = Person()
    print(p1)
    p1.test()
    print(p2)
    p2.test()
    print(p1.sex)
    class Person:
        sex = '男'
        def createVar(selfvar):
            self.var = var
            print(self.__dict__)
    p = Person()
    p.__dict__
    p.createVar('我是实例化后的p')
    __dict__ 以字典的形式 返回对象或者类中的属性和方法
     

    六、属性和方法注意事项

    属性:

    当给类里面的属性 使用对象.属性名 = 值得时候 并不是将类里面得属性值进行修改 而且在当前对象里面创建了一个同名得属性 在查找得时候 会优先取当前对象查找 如果查找不到 则去类中查找 对象和类是一个引用关系 当类里面得属性发生修改 则全部对象全部对应发生改变

    方法:

    方法就是函数,参数和return返回值使用都一样

    七、例子

    class ATM:
        money = 0
        user = ''
        def setMoney(self,money):
            money = int(money)
            if money>=100:
                self.money += money
                print('你好{} 您得余额为 {}'.format(self.user,self.money))
            else:
                print('请输入正确金额')
        def getMoney(self,money):
            money = int(money)
            if money<=self.money and self.money>=100 and money>=100:
                self.money -= money
                print('余额为{}'.format(self.money))
            else:
                print('请输入正确金额')
        def lookMoney(self):
            print('您好{} 您得余额为{}'.format(self.user,self.money))
    zhangsan = ATM()
    zhangsan.user = 'zhangsan'
    zhangsan.setMoney(100)
    zhangsan.getMoney(100)
    zhangsan.lookMoney()
    lisi = ATM()
    lisi.user = '李四'
    lisi.setMoney(1000)
    lisi.getMoney(100)
    lisi.lookMoney()
     

    八、对象属性和类属性

    1. 在对象中 创建了和 类中相同得属性名得时候 在调用会优先调用对象得属性

    2. 对象属性可以被删除 删除以后会去类中查找

    3. 对象属性优先级高于类属性

    4. 对象不可以删除或修改类里面得属性和方法你只有使用权力

    5. 在类中定义得属性 称之为类属性 在对象或者类中方法创建得属性 称之为对象属性

    (1) 绑定对象属性的方法

    实例:

    class A:
        x = 'x' #此刻为类属性
        def createVar(self,var):
            self.var = var  #此属性为对象属性
    a = A()
    a.x = 'x'  #对象属性
    del a.x  #此刻删除得为 对象a里面得x属性
    del a.x   #此刻在删除 为删除类里面得x  不允许修改
    print(a.x)
     

    (2) 绑定类属性

    类名.新得属性名 = 属性值

    实例

    class A:
        pass
    a = A()
    A.newAttr = '给类绑定新属性'
    print(a.newAttr) #给类绑定新属性
     

    注意:

    注意绑定类属性得顺序 需要在对象实例化或者对象调用属性得上方进行绑定类属性 说白了就是 先绑定 后调用(因为加载顺序)

    (3) 系统函数 对类/对象属性得操作(返回bool值)

    hasattr() 判断当前对象/类是否存在某属性

    setattr() 设置对象/类属性

    getattr() 获取对象/类属性

    实例

    class A:
        message = '他年方25 英年早泄'
        def demo(self):
            print('你是怎样调用得呢?',self)
    a = A()
    b = A()
    #判断当前类/对象 是否存在某属性 返回布尔值
    print(hasattr(a,'message')) #True
    print(hasattr(A,'message')) #True
    print(hasattr(a,'name')) #False
    #通过函数获取属性值
    print(getattr(a,'message')) #他年方25 英年早泄
    print(getattr(a,'aaaa','404')) #NOT Found  http状态码
    setattr(a,'x','x') #给对象 a绑定对象属性x 只有当前对象a能够获取到
    setattr(A,'x','x') #给类A绑定类属性以后 所有对象都能够获取到
    print(a.x)
    print(b.x)
     

    九、给对象和类绑定方法

    (1) 给对象绑定方法

    from types import MethodType

    实例

    class A:
        pass
    from types import MethodType
    def func(self):
        print(self)
    a = A()
    b = A()
    a.func = MethodType(func,a)
    # print(a.__dict__) #{'func': <bound method func of <__main__.A object at 0x000001EC1DCDF1D0>>}
    a.func() #只有当前对象有此方法
    b.func() 
     

    只有当前对象有此方法

    (2) 给类绑定方法

    class A:
        def demo(self):
            pass
    def func(self):
        print('你调用我了')
    A.func = func #这个操作和下面得代码是一样得
    """
    a = func
    print(a)
    a(1)
    """
    # print(A.__dict__)
    a = A()
    # print(a.func) #打印函数体
    # print(a.demo) #打印函数体
    A.func('传参')
    b = A()
    b.func()
     

    所有得对象都会有类绑定得方法 (等学完继承以后 不要这么干 因为一旦改动 所有得对象 都会拥有)

    十、__slots__ 限制对象属性得添加

    作用: 能够对对象属性添加起到限制作用 如果添加了slots以外得属性 则抛出attributeError得异常

    实例:

    class A:
        __slots__ = ('name','sex','age') #注意事项 只能使用括号里面得属性 系统属性也不能够使用了
     

    十一、私有属性、私有方法

    (1) 私有属性

    __private_attr:俩个下划线作为开头 ,声明当前属性为私有 只有在类得内部可以使用 不能在类得外部被使用或者 直接访问 在类得内部调用为 self.__private_attr

    私有属性得访问

    对象/类._类名__私有属性名

    其实你的私有属性在存储得时候 自动转换成了 _类名__私有属性名 所以你在调用 __私有属性名得时候 抛出属性错误得异常

    注意:

    虽然这样也可以访问到 但是强烈建议不要这么做 不同得版本解释器可能会将 _类名 改成不同得名字称

    实例

    class B:
        __girlFriend = '小凤'
        def YongMyself(self):
            print('自己内部可以用',self.__girlFriend)
        def update(self):
            # self.__age = 20 #此刻在类得内部创建了一个对象私有属性 __age
            self.__dict__['__age'] = 20  #获取对象中得公有属性 __age 并修改其值
    zhangsan = B()
    print(zhangsan.girlFriend) #AttributeError: 'A' object has no attribute 'girlFriend'
    zhangsan.YongMyself() #可以通过共有得方法 获取私有属性得值  也就是私有在类得内部十可以调用得
    print(B.__dict__)  #查看B类中得所以属性和方法 
    print(zhangsan._B__girlFriend) #通过对象调用私有属性 
    print(B._B__girlFriend)  #通过类来调用私有属性
    zhangsan.__age = 18 #创建了一个名字为__age 得公有对象属性
    zhangsan.update() 
    print(zhangsan.__age)
    print(zhangsan.__dict__)
    print(zhangsan._B__age)
     

    (2) 私有方法

    __private_method: 方法名以俩个下划线作为开头 声明当前方法为 私有方法 只能在类得内部调用 不能够在外部访问 在类得内部调用为 self._private__method

    私有方法得访问

    对象/类._类名__私有方法

    其实你的私有方法在存储得时候 自动转换成了 _类名__私有方法名 所以你在调用 __私有方法名得时候 抛出属性错误得异常

    实例

    class A:
        def __demo(self):
            print('你能不能调用到我呢?')
        def public_method(self): #在公有方法中 调用私有方法
            self.__demo()
    a = A()
    a._A__demo() #私有方法得调用
    A._A__demo(a)
     

    注意:

    私有属性和方法 不会被继承

    十二、装饰器

    可以将方法 像属性一样去调用 起到对值得过滤

    1. @property 对于属性进行获取

    2. @方法名.setter 对属性进行赋值/修改值

    实例

     
    class A:
        sex = 'women'
        __age = 20
        @property
        # def age(self):
        def age(self):
            return self.__age
        @age.setter
        def age(self,age):
            if 1<=age<=100:
                self.__age = age
            else:
                raise ValueError
     a = A()
    a.age = 101
    print(a.age)
     

    十三、继承

    概念: 面向对象编程 最主要得作用就是 代码得重用 实现重用得方法就是 继承机制

    被继承得类 称之为 父类、基类和超类(Base class Super class)

    继承得类称之为 子类

    (1) 单一继承

    通常一个类 如果没有继承得父类得时候 可以继承object类(它是所有类得父类)

    格式

    class Son(BaseClass):
        pass
     

    实例

    class Demo(object):
        pass
    #此刻为继承所有类得超类object   不论你是否继承object  都会默认继承
    class People(object):
        name = ''
        age = 0
        __weight = 0
        money = 100000
        __smallThree = '小凤'
        #定义一个构造方法
        def __init__(self,n,a,w):
            self.name = n
            self.age = a
            self.__weight = w
        def speak(self):
            print("{}说 我今年{}岁了".format(self.name,self.age))
        def __privateSon(self):
            print('私生子 不会被继承')
    class Son(People):
        def smallMother(self):
            # print(self.__smallThree)
            # print(self._People__smallThree) #私有属性和方法 不会被继承
            print(self.name)
            print(self.money)
        def demo(self):
            # self.speak()
            # self.__privateSon() #会在类中查找 但是查找得为 _Son__privateSon()
            self._People__privateSon()
    son = Son('张三',18,70)
    print(son.name,son.money) #拥有了父类得所有公用得东西
    son.smallMother()
    son.demo()
     

    注意:

    1. 父类得私有属性和方法 是不会被继承 但是可以通过 self.__属性名self._类名__方法名 去调用父类得私有属性和方法

    2. 当子类中存在和父类同名得方法时 会将父类得方法覆盖掉(父类方法得重写)

    十四、父类方法得调用

    方法1

    ​ super().方法名()

    方法2

    ​ super(类名,self).方法名

    方法3

    ​ 类名.方法名(self)

    实例

    class Animal(object):
        def __init__(self,name):
            self.name = name
        def saySomething(self):
            print('我是{}'.format(self.name))
    dog = Animal('dog')
    class Dog(Animal):
        def __init__(self,name):
            super().__init__(name)
            # Animal.__init__(self,name) #传入当前对象 self
            # super(Dog,self).__init__(name) #单一继承得时候 不建议加参数  默认会传递   当有多继承得时候 需要使用 传递参数 因为这时候需要指定你想调用得是 哪一个父类得里面得方法
    dog = Dog('dog')
    dog.saySomething()
     

    十五、多继承

    主体结构
     
    class SonClass(base1,base2...):
        pass
     

    将要多继承得类名 写入括号中,以逗号隔开 如果有重复得方法得存在 注意类得摆放顺序

    实例:

    #动物类
    class Animal:
        def animal(self):
            print('属于动物类')
    #跑得类
    class Run(Animal):
        def run(self):
            print('跑的类')
    #能飞得类
    class Fly(Animal):
        def fly(self):
            print('飞的类')
    #哺乳类
    class Lactation(object):
        def lactation(self):
            print('哺乳类')
    #鸟类
    class Bird(object):
        def bird(self):
            print('鸟类')
    #蝙蝠继承了哺乳类
    class BianFu(Fly,Lactation):
        pass
    bianfu = BianFu()
    bianfu.animal()
    bianfu.lactation()
    class Dog(Run,Lactation):
        pass
    dog = Dog()
    dog.animal()
    dog.run()
     

    注意:

    当进行多继承的时候 会将父类中所有的方法和属性 进行继承 如果存在重复的方法 且没有指定的时候 会按照进程父类的摆放顺序 从左至右依次搜索 直到搜索到指定的方法为止

    多继承的父类方法的调用

     
    class A:
        def func(self):
            print('我是A类的func方法')
        def a(self):
            print('我是A类的a方法')
    class B:
        def func(self):
            print('我是B类的func方法')
        def b(self):
            print('我是B类的a方法')
    class D:
        def func(self):
            print('我是d类的func方法')
        def d(self):
            print('我是d类的d方法')
    class C(A,B,D):
        def func(self):
            # B.func(self)
            #当使用super时候 没有传递参数 则按照从左至右的顺序查找
            # super().func()
            # super(C,self).func() #从C类开始向右查找
            # super(A,self).func() #从A类开始 向右查找
            super(B,self).func() #从B类开始 向右查找
    c = C()
    c.func()
    c.d()
     

    十六、类常用的属性

    1. 类名.__doc__ 类的说明

    2. 类名.__name__ 返回当前的类名

    3. 类名.__base__ 返回当前的一个父类

    4. 类名.__bases__ 返回当前的多个父类

    5. 类名.__dict__ 以字典的形式 返回当前类或者对象中的所有的信息

     
    class A:
        """
        这是当前类的说明
        """
        def __init__(self):
            pass
    class C:
        pass
    class B(A,C):
        pass
    print(A.__doc__) #当前类的说明
    print(A.__name__) #返回当前的类名
    print(B.__base__) #返回当前的父类
    print(B.__bases__) #返回当前的多个父类
    print(B.__dict__) #返回当前B类里面的所有信息
     

    十七、静态方法和类方法

    在python的类中 存在3种方法

    1. 静态方法

    2. 类方法

    3. 实例方法

    (1) 静态方法

    被@staticmethod 装饰器修饰的称之为静态方法

    可以在当前类实例化 或者没有实例化的情况下去调用

    实例

    class A:
        def func(self):
            print('func方法')
        #此刻static其实就是一个普通的函数  并且不能够调用类中的属性和方法
        @staticmethod  #只是将 类名.方法名 进行了合理化的处理
        def static(self):
            # return '静态方法'
            self.func()
    a = A()
    # a.static(a)
    A.func()
     

    (2) 类方法

    被@classmethod 装饰器修饰的称之为类方法

    实例

    class A:
        name = '张三'
        def func(self):
            print(self.name,self.sex,'func方法')
        #可以在不进行当前类的实例化 就进行调用 (在方法的内部去实例化)
        #既可以使用类去调用 也可以使用对象调用
        @classmethod
        def classMethod(cls,name,sex):
            # print(cls.name)
            obj = cls()
            obj.name = name
            obj.sex= sex
            return obj
    a = A()
    # a.classMethod()
    # print(A.name)
    # print(A.classMethod('张三','男'))
    A.classMethod('张三','男').func() #将类的实例化 在方法种 节省了实例 并进行对象的连贯操作
     

    十八、类的专有方法

    • __init__:构造方法 在生成对象时 自动调用 作为类的初始化

    • __del__ :析构方法 释放对象的时候时候 可以被del 进行触发

    • __str__ 将值转换成易于人阅读的形式

    • __repr__ 转换为程序员的阅读方式

    • __getattr__ 当获取不存在的属性的时候被触发

    • __add__ 元算符重载 在俩个对象进行相加 的时候触发 (注意 只能是俩个对象相加)

    • __setitem__ 按照索引赋值

    • __getitem__ 按照索引取值

    • __delitem__ 按照索引删除值

    • __len__ 计算当前的长度

    (1)__init____del__的使用

     
    class A:
        f = ''
        def __init__(self,path,method="w"):
            self.f = open(path,method)
        def Read(self,size=1024):
            return self.f.read(size)
        def Write(self,con):
            try:
                return self.f.write(con)
            except:
                return False
        def __del__(self):
            self.f.close()
    a = A('./a.txt')
    a.Write('xx
    ')
    a.Write('yy
    ')
    del a #手动触发
    r = A('./a.txt','r')
    print(r.Read())
    # while True:
    #     pass
     

    (2) __str____repr__ 的使用

    str和repr 都是用来显示内容的 str面向用户 repr是面向程序员的
    触发的时机是不同的
    class A:
        f = ''
        def __init__(self):
            pass
        def Read(self,size=1024):
            pass
        def Write(self,con):
            pass
        def __str__(self):
            return '这是一个空的类'
        def __repr__(self):
            return 'repr'
        def __del__(self):
            pass
    a = A()
     

    注意

    1. str和repr如果单独出现的时候 触发机制都可以

    2. 如果共同存在一个类中的化

      • str

        print(对象)/str(对象)

      • repr

        repr(对象)/在终端下 直接输出对象

    (3)__getattr__ 当调用不存在的属性的时候被触发

    class A:
        f = ''
        def __getattr__(self, item):
            # return '{}属性不存在'.format(item)
            raise AttributeError("{}属性不存在".format(item))
    a = A()
    a.x #会触发 getattr方法
     

    (4) __add__运算符重载

    class A:
        def __init__(self,num):
            self.num = num
        def __add__(self, other):
            return A(self.num+other.num)
        def __str__(self):
            return "num = "+str(self.num)
    a = A(1)
    b = A(2)
    print(a+b)
     

    (5) len,setitem,getitem,delitem的操作

    将类模拟成字典的操作
    class MyDict:
        def __init__(self,key,value):
            self.Dict = {}
            self.Dict[key] = value
        def __setitem__(self, key, value):
            self.Dict[key] = value
        def __getitem__(self, item):
            return self.Dict[item]
        def __len__(self):
            return len(self.Dict)
        def __delitem__(self, key):
            del self.Dict[key]
        def __str__(self):
            return str(self.Dict)
    Dict = MyDict('a','a')
    Dict['b'] = 'b'
    del Dict['a']
    print(Dict)
    print(len(Dict))
    print(Dict['b'])
    print(Dict['x'])
    #将值转换成平方在返回
    class Indexer:
        def __getitem__(self, item):
            return item**2
    obj = Indexer()
    # print(obj[2])
    for i in range(5):
        print(obj[i])
     
  • 相关阅读:
    POJ 1113 Wall
    POJ 3525 Most Distant Point from the Sea
    POJ 3335 Rotating Scoreboard
    POJ 1228 Grandpa's Estate
    POJ 1873 The Fortified Forest
    POJ 2354 Titanic
    POJ 3130 How I Mathematician Wonder What You Are!
    POJ 1106 Transmitters
    POJ 1474 Video Surveillance
    seajs 的研究一 无题
  • 原文地址:https://www.cnblogs.com/gugubeng/p/9715561.html
Copyright © 2020-2023  润新知