第十章:面向对象高级

一、组合

(一) 多继承补充

class People:
    school = 'qinghua'

    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(People):  # 学生类继承人类
    def __init__(self,name,age,gender,stu_id):
        People.__init__(self,name,age,gender)
        self.stu_id = stu_id
        self.courses = []

    def choose(self):
        pass

    def tell_courses_info(self):
        for course_obj in self.courses:
            print("{课程: %s}  {价钱: %s}  {周期:%s}" % (course_obj.name,course_obj.price,course_obj.period))


class Teacher(People):  # 老师类继承人类
    def __init__(self,name,age,gender,level,salary):
        People.__init__(self,name,age,gender)

        self.level = level
        self.salary = salary
        self.courses = []

    def score(self):
        pass

    def tell_courses_info(self):
        for course_obj in self.courses:
            print("{课程: %s}  {价钱: %s}  {周期:%s}" % (course_obj.name,course_obj.price,course_obj.period))


class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

    def tell_courses_info(self):
        print("{课程: %s}  {价钱: %s}  {周期:%s}" % (self.name,self.price,self.period))


stu_obj = Student('tom',9,'male',111)  # 学生
tea_obj = Teacher('wuchangwen',18,'male',99,4500)  # 老师
python_obj = Course('python',22000,'Six months')  # 课程
Java_obj = Course('java',22000,'Six months')  # 课程

stu_obj.courses.append(python_obj)
tea_obj.courses.append(python_obj)
tea_obj.courses.append(Java_obj)


stu_obj.tell_courses_info()
tea_obj.tell_courses_info()


(二) 组合

# 组合与继承都是为了解决类与类直接冗余问题的
# 继承: is-a
# 组合:has-a


class People:
    school = 'IT'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class CourseMixin:
    def tell_courses_info(self):
        print("*******************%s******************" % self.name)
        for course_obj in self.courses:
            course_obj.tell_info()


class Student(CourseMixin, People):
    def __init__(self, name, age, gender, stu_id):
        People.__init__(self, name, age, gender)

        self.stu_id = stu_id
        self.courses = []

    def choose(self):
        pass


class Teacher(CourseMixin, People):
    def __init__(self, name, age, gender, level, salary):
        People.__init__(self, name, age, gender)

        self.level = level
        self.salary = salary
        self.courses = []

    def score(self):
        pass


class Course:
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period

    def tell_info(self):
        print("<名字:%s> <价钱:%s> <周期:%s>" % (self.name, self.price, self.period))


stu_obj = Student('tom', 9, 'male', 111)  # 学生
tea_obj = Teacher('wuchangwen', 18, 'male', 99, 4500)  # 老师
python_obj = Course('python', 22000, 'Six months')  # 课程
Java_obj = Course('java', 22000, 'Six months')  # 课程
linux_obj = Course('linux', 22000, 'Six months')  # 课程

stu_obj.courses.append(python_obj)
tea_obj.courses.append(python_obj)
tea_obj.courses.append(Java_obj)
tea_obj.courses.append(linux_obj)

stu_obj.tell_courses_info()
tea_obj.tell_courses_info()

二、三大特性之多态和鸭子类型

(一)多态

import abc


class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def cry(self):
        pass


class Sheep(Animal):
    def cry(self):
        print('咩咩咩')
        pass


class Cat(Animal):
    def cry(self):
        print('喵喵喵')
        pass


class Dog(Animal):
    def cry(self):
        print('旺旺旺')
        pass


obj1 = Sheep()
obj2 = Cat()
obj3 = Dog()


print('-----------羊的叫声:----------')
obj1.cry()
print('-----------猫的叫声:----------')
obj2.cry()
print('-----------狗的叫声:----------')
obj3.cry()

(二)鸭子类型

'''
什么是鸭子类型?
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。

又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中经常使用,非常灵活,使得python不像java那样专门去弄一大堆的设计模式。

例子如下:
'''
# python推荐鸭子类型
class Animal:
    def cry(self):
        pass


class Sheep(Animal):
    def cry(self):
        print('咩咩咩')


class Cat(Animal):
    def cry(self):
        print('喵喵喵')


class Dog(Animal):
    def cry(self):
        print('旺旺旺')


def in_the_forest(animal):
    animal.cry()


obj1 = Sheep()
obj2 = Cat()
obj3 = Dog()

for i in [obj1,obj2,obj3]:
    in_the_forest(i)


三、绑定方法与非绑定方法

(一)绑定方法

# 注意点:与调节者捆绑,应该由捆绑的调用者调用,调用者在调用时会将自身当作第一个参数传入
# 1.1 绑定给对象的方法:类中定义的函数默认都是绑定给对象的,应该由对象来调用,会对象自己当作第一个参数传入


class Cat:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def tell_info(self):
        print("{%s:%s}" % (self.name, self.age))


obj = Cat('Tom', 3)
obj.tell_info()

# 1.2 绑定给类的方法:在类中定义的函数上添加装饰器classmethod,应该由类来调用,会类自己当作第一个参数传入


class Cat:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def tell_info(self):
        print("{%s:%s}" % (self.name, self.age))


    @classmethod
    def f1(cls):
        print(cls)


# obj = Cat('Tom', 3)
# obj.tell_info()

# print(Cat.tell_info())
print(Cat.f1)
# Cat.tell_info()

Cat.f1()

(二)非绑定方法

# 注意:不予任何人捆绑,谁都可以来调用,就是一个普通函数,没有自动传参的效果
# 非绑定方法:在类中定义的函数上添加装饰器staticmethod,谁都可以来调用,就是一个普通函数,没有自动传参的效果


class Cat:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def tell_info(self):
        print("{%s:%s}" % (self.name, self.age))


    @classmethod
    def f1(cls):
        print(cls)


    @staticmethod
    def f2(x, y):
        print(x, y)


obj = Cat('Tom', 3)


print(Cat.f2)
print(obj.f2)

Cat.f2(1, 2)
obj.f2(3, 4)

应用场景

settings

IP="192.168.11.11"
PORT=3306
import settings
import uuid


class Mysql:
    def __init__(self, ip, port):
        self.id = self.create_id()
        self.ip = ip
        self.port = port

    def tell_info(self):
        print("{%s:%s}" % (self.ip, self.port))


    @classmethod
    def from_conf(cls):
        return cls(settings.IP,settings.PORT)


    @staticmethod
    def create_id():
        return uuid.uuid4()


obj1 = Mysql('172.168.10.11', 3306)
obj2 = Mysql.from_conf()
print(obj2.__dict__)

print(Mysql.create_id())
print(obj2.create_id())

四、反射

class Cat:
    x = 123

    def __init__(self,name):
        self.name = name


obj = Cat('Tom')
res = hasattr(obj, 'name')  # 判断 name in obj.__dict__
print(res)

res1 = getattr(obj, 'name')  # obj.name
print(res1)

setattr(obj, 'name', 'TOM')  # obj.name = 'TOM'
print(obj.name)

delattr(obj, 'name')  # 清除name
print(obj.__dict__)

print(hasattr(Cat, 'x'))
class Ftp:
    def get(self):
        print('get...')

    def put(self):
        print('put...')


obj = Ftp()
cmd = input('>>>:')
if hasattr(obj, cmd):
    f = getattr(obj, cmd)
    print(f)
    f()

五、内置方法

# __方法__:称之为内置方法,定义在类内部,都不是直接调用的,都是在满足某种条件下自动触发执行的
# __str__:在打印对象时自动触发执行,将返回值当作打印的结果输出,注意返回值必须是字符串类型


class Cat:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def __str__(self):
        return "{%s:%s:%s}" % (self.name, self.age, self.gender)


obj = Cat('Tom', 1.5, 'male')
print(obj)  # print(obj.__str__())
# len(obj)  # obj.__len__


l = [1,2,3,4,5,6]
print(l)

x=9
print(x)


# __del__:删除对象内存空间之前,自动触发执行,用于回收操作系统资源
class Bar:
    pass


class Foo(Bar):
    def __init__(self, x, y,filepath):
        self.x = x
        self.y = y
        self.f=open(filepath,mode='r',encoding='utf-8')

    # def __del__(self):
    #     print('回收系统资源的代码')
    #     self.f.close()


obj=Foo(111,222,'a.txt')
# del obj
# print('============main===============')


print(isinstance(obj,Foo))
print(isinstance(10,int))

print(issubclass(Foo,Bar))


class Foo:
    pass


obj=Foo()
print(hasattr(obj,"__str__"))
print(hasattr(obj,"__del__"))

作者:吴常文
出处:https://blog.csdn.net/qq_41405475
本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

猜你喜欢

转载自blog.csdn.net/qq_41405475/article/details/114896549
今日推荐