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\n")
f1.write("testtxettestxt\n")
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 \n 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)
posted @ 2019-04-26 20:16  生生不息.连绵不绝  阅读(148)  评论(0编辑  收藏  举报