面向对象


"""
    1.类与对象

        大  千 世界到处都是东西, Python世界神马都是对象 --De8uG
        类 = 模板
        对象 :某个具体元素
        对象 = 实例
        数据和方法的封装(面向对象三大特性之一),用对象统一调用

    2.如何定义一个类

        class 类的名称:缩进+内容
        举例: 人,学生,车,电脑,日志,游戏war3
        私有变量:__name,不能被继承
        内部变量:_开头
        通过方法修改私有数据,对数据进行保护
        查看类型:isinstance,type
        属性只读:@property,@x.setter

    3.方法中的self是怎么回事

        实例本身
        放到第一个参数,区别于普通函数
        通用名为self

    4.特殊方法

        __init__: 把各种属性绑定到self
        __slots__: 限制实例的动态属性,减少内存消耗,tuple类型
        __str__: 对象的说明文字
        __eq__: 比较对象是否相等
        https://docs.python.org/3/reference/datamodel.html#special-method-names
        classmethod 与 staticmethod : classmethod 会把类本身作为第一个参数传入

    5.面向对象三大特征

        继承

        子类:直接使用父类的属性和方法,还可以自定义【覆盖,重写】
        父类:规定基本功能
        举例:学生,车
        多重继承:MixIn,混入多种功能,避免层次过于复杂的继承

        多态

        子类继承父类的方法,但是每个子类会运行自己继承后的方法。一个方法,多种动态

        封装

    6.元编程

        运行时动态创建类和函数
        metaclass -> class -> obj
        __new__

    7.7种可调用对象

        用户定义的函数: 使用def语句或lambda表达式创建
        内置函数:如len
        内置方法:如dict.get
        方法:在类定义体中的函数

        类

        类的实例: 如果类定义了 __call__ , 那么它的实例可以作为函数调用.
        生成器函数: 使用 yield 关键字的函数或方法.

    8.反射都能用来干什么

        getattr(obj, 'attr')
        setattr
        hasattr

"""


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

    def walk(self):
        print(f'{self.name}在走路,今年看起来{self.age}岁')


dongli = People('dongli', 18)
dongli.walk()

print(dongli)
print(type(dongli))  # 查看类型
print(isinstance(dongli, People))  # 查看是否属于某个类的实例


class Car:
    def __init__(self, brand, price, wheels, power):

        self._brand = brand  # 内部变量
        self.price = price
        self.wheels = wheels
        self.power = power
        self.__speed = 0  # 私有变量 不能被继承

    def run(self, action):
        print(f'{self.brand} is running')
        if action == '1':
            self.__speed += 1 * 10  # 修改私有变量
            print(f'当前速度是:{self.__speed} km/h')

    def start(self):
        print(f'{self.brand}is on')

    @property  # 只读 get方法 把方法变成属性
    def speed(self):
        return self.__speed

    @property
    def brand(self):
        return self._brand

    @brand.setter  # 添加set 方法 可以被赋值
    def brand(self, brand):
        if not isinstance(brand, str):
            raise TypeError('牌子的类型是字符串')
        self._brand = brand

    @property
    def info(self):
        return f'{self.brand}: {self.price}'

auto = Car('auto', 30000, 4, 'oil')
auto.run('1')
print(auto.info)
print(auto.speed)
auto.brand = 'auto2018'
print(auto.brand)
# auto.brand = 123

tesla = Car('Tesla', 100000, 4, 'electric')
tesla.run('1')
tesla.price = 9999
print(tesla.price)
tesla.name = "teslacar"  # 动态添加属性 不建议
print(tesla.name)

"""
    self是怎么回事:

        实例本身放到第一个参数,区别于普通函数通用名为self
        假如你有一个类称为MyClass和这个类的一个实例MyObject。
        当你调用这个对象的方法MyObject.method(arg1,arg2)的时候,
        这会由Python自动转为MyClass.method(MyObject, arg1, arg2)

"""


class game:

    def __init__(self):
        pass

    def play(self, game_name='麻将'):
        print('play', game_name)

g = game()
g.play()
g.play('扎金花')


"""
    特殊方法
    __init__: 把各种属性绑定到self
    __slots__: 限制实例的动态属性,减少内存消耗,tuple类型
    __str__: 对象的说明文字
    __eq__: 比较对象是否相等
    https://docs.python.org/3/reference/datamodel.html#special-method-names
    classmethod 与 staticmethod : classmethod 会把类本身作为第一个参数传入


"""


class Computer:

    def __init__(self, name, mem, cpu):
        self.name = name
        self.mem = mem
        self.cpu = cpu
    
    def play(self, game='QQ游戏'):
        print('play', game)

pc1 = Computer('dongli', '16g', 4)
print(pc1)
pc1.mem = '32G'
print(pc1.mem)
pc1.disk = '500G'

print(pc1.disk)


class Computer1:

    __slots__ = ('name', 'mem', 'cpu')

    def __init__(self, name='dongli', mem='8G', cpu=4):
        self.name = name
        self.mem = mem
        self.cpu = cpu

    def __str__(self):  # 对象的说明文字
        return f'{self.name}'

    def __eq__(self, other):  # 比较对象相等
        return self.cpu == other.cpu

    @classmethod  # 通过类方法创建对象
    def pc_new(cls, info):
        name, mem, cpu = info.split(' ')
        return cls(name, mem, cpu)

    @staticmethod  # 静态方法 不需要实例化直接调用
    def calc(x, y):
        return x + y

pc2 = Computer1()
print(pc2)
print(pc2.mem)
pc2.mem = '16G'
print(pc2.mem)

# pc2.disk = '1T'
# print(pc2.disk)

print(pc2)
pc3 = Computer('jiamei', '16G', 4)

print(pc2 == pc3)

pc3 = Computer1.pc_new('dongdong 24G 2')
print(pc3)

print(Computer1.calc(1, 2))

""" 封装 继承 多态 """


class Book:
    def __init__(self, name, author):
        self.name = name
        self.author = author

    def say(self):
        print('这是一本书!')
    
    def warr(self):
        print('好好学习 天天向上!')


class Mathbook(Book):
    def __init__(self, name='math', author='dongli'):
        super().__init__(name, author)

    def say(self):
        print('这是一本数学书!')

newbook = Mathbook()
newbook.say()
newbook.warr()


""" 元编程 """


class demo(type):
    def __new__(cls, name, bases, my_dict):
        print('demo demo!')  
        new_demo = super().__new__(cls, name, bases, my_dict)
        return new_demo


class demo_meta(metaclass=demo):  # 运行时通过metaclass 创建对象

    def say(self):
        print('888')

""" 
    可调用对象

    函数后的()其实是调用运算符,任何可以添加()的为可调用对象
    用户定义的函数: 使用def语句或lambda表达式创建
    内置函数:如len
    内置方法:如dict.get, 底层由c语言实现
    方法:在类定义体中的函数
    类:运行时候通过__new__创建新对象,然后__init__完成初始化,本质还是在调用函数。
    类的实例: 如果类定义了 __call__ , 那么它的实例可以作为函数调用,表现像个函数。
    生成器函数: 使用 yield 关键字的函数或方法,返回生成器对象

"""

"""
    hasattr(obj, attr):
    这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
    getattr(obj, attr):
    调用这个方法将返回obj中名为attr值的属性的值。
    setattr(obj, attr, val):
    调用这个方法将给obj的名为attr的值的属性赋值为val。
"""


"""汽车工厂"""


# 汽车类
class car(type):
    def __new__(cls, name, bases, my_dict):
        new_car = super().__new__(cls, name, bases, my_dict)
        return new_car


class Audi(metaclass=car):
    def info(self):
        print('Audi 汽车')


class Tesla(metaclass=car):
    def info(self):
        print('Tesla 汽车')


# 工厂类
class Factory:
    def create(self):
        print('创建汽车,工厂基类')


class AudiFactory(Factory):
    def create(self):
        print('创建Audi汽车')
        return Audi()


class TeslaFactory(Factory):
    def create(self):
        print('创建Tesla汽车')
        return Tesla()

AudiFactory().create().info()
TeslaFactory().create().info()



最后更新于:2018-06-14 22:32:43