zoukankan      html  css  js  c++  java
  • 190411Python面向对象编程

    一、面向对象的概念

    • 类:把一类事物的相同特征抽取出来整合到一起就是一个类,类是一个抽象的概念
    • 对象:基于类创建的一个具体的事物
    class People(object):
        '这是一个人类的类'
    
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def say_hello(self):  #函数属性
            print("%s 您好!" % self.name)
    
        def get_attr(self):
            print("您今年已经 %s 岁了" % self.age)
    
        def eat_food(self,food):
            print("%s 正在吃 %s." % (self.name,food))
    
    p1 = People("Dongfei",18,"M")  #实例化,p1 = People.__init__(p1,"dongfei",18,"M")
    p1.say_hello()
    p1.get_attr()
    p1.eat_food("饺子")
    
    
    print(People.__dict__)  #查看类的属性字典
    print(People.__name__)  #类名
    print(People.__doc__)  #描述
    print(People.__base__)
    print(People.__bases__)
    print(People.__module__)  #显示这个类所在哪个模块
    print(People.__class__)  #类型
    

    二、类属性的增删查改

    class People(object):
        '这是一个人类的类'
        addr = "earth"
    
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def say_hello(self):  #函数属性
            print("%s 您好!" % self.name)
    
        def get_attr(self):
            print("您今年已经 %s 岁了" % self.age)
    
        def eat_food(self,food):
            print("%s 正在吃 %s." % (self.name,food))
    
    print(People.addr)  #查,earth
    
    People.addr = "Mars"  #改
    print(People.addr)  #Mars
    
    People.status = "alive"  #增
    print(People.status)  #alive
    
    del People.addr  #删
    

    三、实例属性的增删查改

    class People(object):
        '这是一个人类的类'
        addr = "earth"
    
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def say_hello(self):  #函数属性
            print("%s 您好!" % self.name)
    
        def get_attr(self):
            print("您今年已经 %s 岁了" % self.age)
    
        def eat_food(self,food):
            print("%s 正在吃 %s." % (self.name,food))
    
    p1 = People("Dongfei",18,"M")
    print(p1.__dict__)  #实例属性字典,{'gender': 'M', 'age': 18, 'name': 'Dongfei'}
    
    print(p1.name)  #查,Dongfei
    print(p1.addr)  #类的数据属性,earth
    
    p1.hobby = "Python"  #增
    print(p1.__dict__)  #{'name': 'Dongfei', 'hobby': 'Python', 'age': 18, 'gender': 'M'}
    
    p1.age = 19  #改
    print(p1.__dict__)  #{'age': 19, 'name': 'Dongfei', 'hobby': 'Python', 'gender': 'M'}
    
    del p1.gender
    print(p1.__dict__)  #{'name': 'Dongfei', 'age': 19, 'hobby': 'Python'}
    

    四、静态属性,类方法,静态方法

    • property
    class Room():
        x = 1
    
        def __init__(self,name,owner,width,length,heigh):
            self.name = name
            self.owner = owner
            self.width = width
            self.length = length
            self.heigh = heigh
    
        @property  #静态属性,可以封装逻辑
        def cal_area(self):
            # print("%s 的 %s 面积是 %s" %(self.owner,self.name,self.width*self.length))
            return self.width*self.length
    
    r1 = Room("loushi", "dongfei", 10, 10, 5)
    print(r1.x)  #1
    print(r1.cal_area)  #100
    
    • classmethod
    class Room():
        x = 1
    
        def __init__(self,name,owner,width,length,heigh):
            self.name = name
            self.owner = owner
            self.width = width
            self.length = length
            self.heigh = heigh
    
        @classmethod  #类方法,直接用类来调用
        def get_x(cls):
            return cls.x
    
    print(Room.get_x())  #1,调用类方法
    
    • staticmethod
    class Room():
        x = 1
    
        def __init__(self,name,owner,width,length,heigh):
            self.name = name
            self.owner = owner
            self.width = width
            self.length = length
            self.heigh = heigh
    
        @staticmethod  #静态方法,类的工具包,不能使用类变量和实例变量
        def Bedroom(name):
            print("%s is sleepping ..." % name)
    
    Room.Bedroom("dongfei")  #类调用
    
    r1 = Room("loushi", "dongfei", 10, 10, 5)
    r1.Bedroom("dongfei")  #实例调用
    

    五、组合

    • 示例
    class Hand():
        pass
    class Body():
        pass
    class Foot():
        pass
    
    class Person():
        def __init__(self,id,name):
            self.Id = id
            self.Name = name
            self.Hand = Hand()
            self.Body = Body()
            self.Foot = Foot()
    
    p1 = Person('000001', 'jack')
    print(p1.__dict__)  #{'Id': '000001', 'Name': 'jack', 'Foot': <__main__.Foot object at 0x000000000106B278>, 'Hand': <__main__.Hand object at 0x000000000106B208>, 'Body': <__main__.Body object at 0x000000000106B240>}
    
    • 示例2
    class School():
        def __init__(self,name,addr):
            self.name = name
            self.addr = addr
    
    class Course():
        def __init__(self,name,price,school_name,addr):
            self.name = name
            self.price = price
            self.school = School(school_name,addr)
    
    c1 = Course("python",1000,"希望小学","beijing")
    print(c1.school.name)
    

    六、面向对象的三大特性

    • 继承、接口继承
    1. 继承顺序:深度优先、广度优先,python3 都是新式类,遵循广度优先
    class ParentClass1():
        pass
    
    class ParentClass2():
        pass
    
    class SubClass1(ParentClass1):  #单继承
        pass
    
    class SubClass2(ParentClass1,ParentClass2):  #多继承
        pass
    
    class ParentClass1():
        x = 1
    
        def __init__(self,name):
            self.name = name
    
    class ParentClass2():
        y = 2
    
    class SubClass1(ParentClass1):  #单继承
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    class SubClass2(ParentClass1,ParentClass2):  #多继承
        pass
    
    s1 = SubClass1("taiwen",20)
    print(s1.x)  #1
    print(s1.name)  #taiwen
    print(s1.age)  #20
    
    import abc
    
    class All_File(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod  #接口继承,子类中必须要定义read方法
        def read(self):
            pass  #接口类不需要写逻辑
    
        @abc.abstractmethod
        def write(self):
            pass
    
    class Disk(All_File):
    
        def read(self):
            print('disk read')
    
        def write(self):
            print('disk write')
    
    d1 = Disk()
    d1.write()
    
    • 多态:不同的对象去调用相同的方法就是多态的体现
    • 封装
    class People:
        _star1 = "earth1"
        __star2 = "earth2"  # 限制类的外部访问
        def __init__(self,id,name,age):
            self.id = id
            self.name = name
            self.age = age
    
    p1 = People(1,"jack",20)
    print(p1._star1)  #earth1
    print(p1._People__star2)  #earth12
    

    七、子类中调用父类的方法

    class Vehicle:
        Country = "China"
        def __init__(self,name,speed,load,power):
            self.name = name
            self.speed = speed
            self.load = load
            self.power = power
    
        def run(self):
            print("runing")
    
    class Subway(Vehicle):
    
        def __init__(self,name,speed,load,power,line):
            Vehicle.__init__(self,name,speed,load,power)  #继承父类的数据属性
            self.line = line
    
        def show_info(self):
            print(self.name, self.speed,self.power,self.line)
    
        def run(self):  #子类中调用父类的方法
            Vehicle.run(self)
            print("%s %s running" % (self.name,self.line))
    
    line10 = Subway("地铁","50m/s",10000000,"Electricity",10)
    
    line10.show_info()
    line10.run()
    
    • super()方法
    class Vehicle:
        Country = "China"
        def __init__(self,name,speed,load,power):
            self.name = name
            self.speed = speed
            self.load = load
            self.power = power
    
        def run(self):
            print("runing")
    
    class Subway(Vehicle):
    
        def __init__(self,name,speed,load,power,line):
            # Vehicle.__init__(self,name,speed,load,power)  #继承父类的数据属性
            super().__init__(name,speed,load,power)  # == super(Subway, self).__init__(name,speed,load,power)
            self.line = line
    
        def show_info(self):
            print(self.name, self.speed,self.power,self.line)
    
        def run(self):  #子类中调用父类的方法
            # Vehicle.run(self)
            super().run()
            print("%s %s running" % (self.name,self.line))
    
    line10 = Subway("地铁","50m/s",10000000,"Electricity",10)
    
    line10.show_info()
    line10.run()
    

    八、反射

    1. 程序可以访问、检测和修改它本身状态或行为的一种能力
    • hasattr
    print(hasattr(b1,'name'))  #检测b1实例中有没有name这个属性
    
    • getattr
    print(getattr(b1,'name'))  #获取b1实例中name属性,没有则会报错
    print(getattr(b1,'name123',"查无此属性"))  #没有返回“查无此属性”
    
    • setattr
    setattr(b1,'sb',True)  #给对象设置属性
    print(getattr(b1,'sb'))
    
    • delattr
    delattr(b1,'addr')
    print(getattr(b1,'addr','无此属性'))
    

    九、动态导入模块

    import importlib
    m = importlib.import_module("m1.t1")
    print(m)
    m.t()
    

    十、__getattr__、__delattr__、__setattr__ 在类中是用法

    • 示例1
    class T:
        def __init__(self,x):
            self.x = x
    
        def __getattr__(self, item):  #调用不存在的方法时会执行
            print("in the getattr")
    
        def __delattr__(self, item):  #删除属性时会触发
            self.__dict__.pop[item]
    
        def __setattr__(self, key, value):  #执行__init__时会触发
            print("in the setattr")
            #self.key = value  #会进入递归
            self.__dict__[key] = value
    
    t1 = T(100)
    
    res = getattr(t1,"nonono")  #in the getattr
    print(res)  #None
    
    delattr(t1,"x")  #in the delattr
    
    setattr(t1,"y",99)
    print(t1.__dict__)  #{'y': 99, 'x': 100}
    
    • 示例2
    class Foo:
        def __init__(self,name):
            self.name = name
    
        def __getattr__(self, item):
            print("[%s] 不存在" % item)
    
        def __setattr__(self, key, value):  #定制设置属性的过程
            print("run setattr")
            if type(value) is str:
                print("开始设置")
                self.__dict__[key] = value
            else:
                print("只支持字符串")
    
        def __delattr__(self, item):  #删除时触发
            print("run delattr",item)
            self.__dict__.pop(item)
    
    
    f1 = Foo("dongfei")
    f1.age = "18"  #触发__setattr__
    print(f1.__dict__)
    
    del f1.name
    print(f1.__dict__)
    

    十一、自定义标准class

    • 继承/派生
    class List(list):
        def show_medlle(self):
            mid_index = int(len(self)/2)
            return self[mid_index]
    
        def append(self, p_object):
            print("只能添加字符串类型")
            if type(p_object) is str:
                super().append(p_object)
    
    l1 = List("helloworld")
    
    print(l1)
    print(l1.show_medlle())
    
    l1.append("abc")
    print(l1)
    
    • 授权
    import time
    
    class FileHandl:
        def __init__(self,filename,mode="r",encoding="utf-8"):
            self.file = open(filename,mode,encoding=encoding)
    
        def write(self,line):
            date = time.strftime("%Y-%m-%d %X")
            self.file.write("%s %s" % (date,line))
    
        def __getattr__(self, item):
            print(item)
            return  getattr(self.file,item)
    
    f1 = FileHandl("a.txt", "r+")
    # print(f1.read())
    
    f1.write("testtxettestxt
    ")
    f1.write("testtxettestxt
    ")
    f1.seek(0)
    print(f1.read())
    

    十二、面向对象进阶

    1、isinstance和issubclass

    • isinstance
    class Foo:
        pass
    
    f1 = Foo()
    
    print(isinstance(f1,Foo))  #判断f1实例是否由Foo类实例化而来的
    
    • issubclass
    class Foo:
        pass
    
    class Bar(Foo):
        pass
    
    print(issubclass(Bar,Foo))  #Bar是否是Foo的子类
    

    2、getattribute

    class Foo:
        def __init__(self,name):
            self.name = name
    
        def __getattr__(self, item):  #当getattribute抛出AttributeError异常时执行
            print("in the getattr")
    
        def __getattribute__(self, item):  #不管属性是否可以找到,都会触发getattribute
            print("in the getattribute")
            raise AttributeError("抛出异常")
    
    f1 = Foo("hello")
    f1.nonono  #in the getattribute 
     in the getattr
    

    3、getitem、setitem和delitem

    class Foo:
        def __getitem__(self, item):
            print("getitem")
            return self.__dict__[item]
    
        def __setitem__(self, key, value):  #支持字典的方式设置值
            print("setitem")
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            print("delitem")
            self.__dict__.pop(key)
    
    f1 = Foo()
    print(f1.__dict__)
    f1["name"] = "dongfei"
    print(f1.__dict__)
    del f1["name"]
    print(f1.__dict__)
    f1["name"] = "jack"
    print(f1["name"])
    

    4、str

    class Foo():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __str__(self):  #控制实例的返回值
            return "foo 的返回值:名字[%s] 年龄[%s]" %(self.name,self.age)
    
    f1 = Foo("dongfei",18)
    print(f1)  #foo 的返回值:名字[dongfei] 年龄[18]
    

    5、repr

    class Foo():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __repr__(self):  #f1.__repr__()  #应用在解释器中
            return "foo 的返回值:名字[%s] 年龄[%s]" %(self.name,self.age)
    
    f1 = Foo("dongfei",18)
    

    6、format

    format_dic = {
        'ymd':'{0.year}:{0.mon}:{0.day}',
        'mdy':'{0.mon}:{0.day}:{0.year}'
    }
    
    class Date:
        def __init__(self,year,mon,day):
            self.year = year
            self.mon = mon
            self.day = day
    
        def __format__(self, format_spec):
            print('run format')
            print(format_spec)
            if not format_spec or format_spec not in format_dic:
                format_spec = 'ymd'
            fm = format_dic[format_spec]
            return fm.format(self)
    
    d1 = Date(2019,4,19)
    
    x = '{0.year} {0.mon} {0.day}'.format(d1)
    y = '{0.year}:{0.mon}:{0.day}'.format(d1)
    print(x)
    print(y)
    z = format(d1)
    print(z)
    

    7、slots

    为了节省内存空间,可以用slots代替dict,实例只能定义slots已有的属性

    class Foo:
        __slots__ = "name"
    
    f1 = Foo()
    f1.name = "dongfei"
    print(f1.name)
    print(f1.__slots__)
    

    8、doc

    class Foo:
        '类的描述信息'
        pass
    
    print(Foo.__doc__)  #类的描述信息,该属性不能被继承
    

    9、del

    class Foo:
        def __init__(self,name):
            self.name = name
    
        def __del__(self):  #python解释器删除时触发
            print("析构函数执行。。。")
    
    f1 = Foo("jack")
    del f1.name
    

    10、call

    class Foo:
        def __call__(self, *args, **kwargs):
            print("in the call")
    
    f1 = Foo()
    f1()  #in the call
    

    11、iter和next

    class Foo:
        def __init__(self,n):
            self.n = n
    
        def __iter__(self):  #将对象变成可迭代的对象
            return self
    
        def __next__(self):
            if self.n == 1000:
                raise StopIteration("终止")
            self.n += 1
            return self.n
    
    f1 = Foo(1)
    
    for i in f1:  #f1.__iter__()
        print(i)
    
    • 斐波那契数列
    class Fib:
        def __init__(self):
            self._a = 1
            self._b = 1
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self._a > 10000:
                raise StopIteration("终止")
            self._a, self._b = self._b, self._a + self._b
            return self._a
    
    f1 = Fib()
    for i in f1:
        print(i)
    

    12、描述符get,set,delete (新式类的特性)

    类属性>数据描述符>实例属性>非数据描述符(无set方法的描述符)

    class Foo:
        def __get__(self, instance, owner):  #调用一个属性时触发
            print("in the get")
    
        def __set__(self, instance, value):  #为一个属性赋值时触发
            print("in the set")
    
        def __delete__(self, instance):  #用del删除属性时触发
            print("in the delete")
    
    class Bar:
        x = Foo()
    
    b1 = Bar()
    b1.x  #in the get
    b1.x = 1  #in the set
    del b1.x  #in the delete
    
    • 实例化前检查参数类型
    class Typed:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
    
        def __get__(self, instance, owner):
            # print("run get")
            # print('instance, owner',instance,owner)
            return instance.__dict__[self.key]
    
        def __set__(self, instance, value):
            # print("run set")
            # print('instance, value', instance, value)
            if not isinstance(value,self.expected_type):
                raise TypeError("type error")
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            # print("run delete")
            instance.__dict__.pop(self.key)
    
    
    class People:
        name = Typed("name",str)
        age = Typed("age",int)
        salary = Typed("salary",float)
    
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    
    p1 = People("dongfei",18,1800)
    # print(p1.name)
    # del p1.age
    # print(p1.__dict__)
    print(p1.name,p1.age,p1.salary)
    

    13、enter和exit

    class Open:
        def __init__(self,name):
            self.name = name
    
        def __enter__(self):
            print("run enter")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("run exit")
    
    with Open("a.txt") as f:  #在此触发__enter__,enter返回值赋值给f
        print("xxx")
        #代码结束时触发__exit__
    
    class Open:
        def __init__(self,name):
            self.name = name
    
        def __enter__(self):
            print("run enter")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("run exit")
            print(exc_type)  #异常类
            print(exc_val)  #异常的值
            print(exc_tb)  #异常的异常信息
            return True
    
    with Open("a.txt") as f:  #在此触发__enter__,enter返回值赋值给f
        print(f)
        print(nono)
        print("xxx")
        #代码结束时触发__exit__
    
    #输出:
    # run enter
    # <__main__.Open object at 0x0000000001084160>
    # run exit
    # <class 'NameError'>
    # name 'nono' is not defined
    # <traceback object at 0x000000000108A288>
    

    十三、类的装饰器

    def Typed(**kwargs):
        def deco(obj):
            print(kwargs)
            print(obj)
            for key,val in kwargs.items():
                setattr(obj,key,val)
            return obj
        return deco
    
    @Typed(x=1,y=2)
    class Foo:
        pass
    print(Foo.__dict__)
    
    @Typed(name="dongfei")
    class Bar:
        pass
    print(Bar.__dict__)
    
    • 描述符和装饰器的应用示例
    class Typed:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
    
        def __get__(self, instance, owner):
            # print("run get")
            # print('instance, owner',instance,owner)
            return instance.__dict__[self.key]
    
        def __set__(self, instance, value):
            # print("run set")
            # print('instance, value', instance, value)
            if not isinstance(value,self.expected_type):
                raise TypeError("type error")
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            # print("run delete")
            instance.__dict__.pop(self.key)
    
    def deco(**kwargs):
        def wrapper(obj):
            # print(kwargs)
            # print(obj)
            for key,val in kwargs.items():
                setattr(obj,key,Typed(key,val))
            return obj
        return wrapper
    
    @deco(name=str,age=int,salary=float)
    class People:
        # name = Typed("name",str)
        # age = Typed("age",int)
        # salary = Typed("salary",float)
    
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    
    p1 = People("dongfei",18,1800.1)
    # print(p1.name)
    # del p1.age
    # print(p1.__dict__)
    print(p1.name,p1.age,p1.salary)
    print(People.__dict__)
    

    十四、利用描述符和装饰器自定制property

    class Lazyproperty:
        def __init__(self,func):
            self.func = func
    
        def __get__(self, instance, owner):
            print("run get")
            if instance is None:
                return self
            res = self.func(instance)
            setattr(instance,self.func.__name__,res)  #缓存功能
            return res
    
        # def __set__(self, instance, value):
        #     pass
    
    class Room:
        def __init__(self,name,width,length):
            self.name = name
            self.width = width
            self.length = length
    
        @Lazyproperty  #area = Lazproperty(area)
        def area(self):
            return self.width * self.length
    
    r1 = Room("卧室",3,4)
    print(r1.area)
    print(Room.area)
    print(r1.__dict__)
    print(r1.area)
    
  • 相关阅读:
    在Vue中使用Echart图表库。【全网最简单】
    asp.net core的授权过滤器中获取action上的Attribute
    用node.js给C#写一个数据表的实体类生成工具
    node.js操作MySQL数据库
    基于node.js的爬虫框架 node-crawler简单尝试
    Angular双向绑定简单理解
    使用.Net core3.0 开发斗图小程序后端+斗图小程序
    Django的命令操作,python
    python,函数式编程
    python 推导式的用法
  • 原文地址:https://www.cnblogs.com/L-dongf/p/10776362.html
Copyright © 2011-2022 走看看