Python面向对象

1、写一个类

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

    def run(self):
        return "this is function run"

    def __getattr__(self, item):
        return "111"


F = Foo("张三", 12)
print(F.age)  # 12
print(F.run)  # <bound method Foo.run of <__main__.Foo object at 0x000001292A4F71C0>>
print(F.run())  # this is function run
print(F.xxxxx)  # 111

1、__getattr__方法,访问类中不存在的成员时触发,访问对象中存在的成员时不会触发

2、__getattribute__方法,访问任何成员都会先执行他,报错是因为返回的999,应该判断是否是函数再执行他,这里是示例代码:

class Foo:
    count = 0
    def __init__(self, name, age):
        self.name = name
        self.age = age
        # 统计实例化了几个对象,所有对象能共享的数据
        Foo.count += 1
    def run(self):
        return "this is function run"

    def __getattr__(self, item):
        return "111"

    def __getattribute__(self, item):
        print("__getattribute__执行了")
        return 999


F = Foo("张三", 12)
print(F.age)  # 999
print(F.run)  # 999
print(F.run())  
print(F.xxxxx)  

 3、property的使用,把方法变成不加括号可调用

class Foo:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def run(self):
        return "self是" + str(self) + "这是Foo下边的run方法"

    @property
    def get_name(self):
        return self.__name

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        self.__age = age

    @age.deleter
    def age(self):
        del self.__age

F = Foo("张三", 12)
print("F的年龄", F.age)  # F的年龄 12
print(F.get_name)  # 张三
F.age = 1
print("F的年龄", F.age)  # F的年龄 1
del F.age
print("F的年龄", F.age)  # AttributeError: 'Foo' object has no attribute '_Foo__age'

print(Foo.run(F))

4、__str__方法,指定打印对象时的输出

5、__del__方法,对象销毁之前执行

2、写两个类(继承,封装,多态)

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

    def run(self):
        self.sleep()
        return "self是" + str(self) + "这是Foo下边的run方法"

    def sleep(self):
        return "self是" + str(self) + "这是Foo下边的sleep方法"


class Boo(Foo):
    def __init__(self):
        self.x = 123

    def sleep(self):
        return "self是" + str(self) + "这是Boo下边的sleep方法"


F = Foo("张三", 12)
print(F.run())
###  self是<__main__.Foo object at 0x000002BFF5FC71C0>这是Foo下边的run方法
B = Boo()
print(B.run())
###  self是<__main__.Boo object at 0x000002BFF620C610>这是Foo下边的run方法


注意:子类调用父类的方法,self还是子类对象本身,所以,F.run()里执行的sleep是Foo的,B.run()执行的sleep是Boo的;

        但是当sleep方法是隐藏方法(__sleep())的话,那就肯定访问的是Foo的sleep方法,因为隐藏方法的名字被改成了:_类名__方法名,父子的方法名不是一样的了;

继承( )

派生

子类除了父类还需实例化出更多的属性,先调用父类的init,再写自己需实例化的属性

class Human:
    star = "earth"

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


class Chinese(Human):
    language = "Chinese"

    def __init__(self, name, age, sex, account):
        super().__init__(name, age, sex)
        self.account = account

    def speak(self):
        print(self.name + "在说" + self.language)


class America(Human):
    language = "English"

    def speak(self):
        print(self.name + "在说" + self.language)


C = Chinese("董永", 18, "男", 1000)
print(C.__dict__)
C.speak()
A = America("泰勒斯威夫特", 18, "女")
print(A.__dict__)
A.speak()

"""
输出:
{'name': '董永', 'age': 18, 'sex': '男', 'account': 1000}
董永在说Chinese
{'name': '泰勒斯威夫特', 'age': 18, 'sex': '女'}
泰勒斯威夫特在说English
"""

查找类的继承顺序:

非菱形继承不分新式类和经典类,也没有深度和广度的概念,就是一条分支走完走另一条,新式类继承object,经典类不继承object 

对于菱形继承的深度优先和广度优先,都是按分支找完,区别就是深度优先会在第一条分支去找顶点类,广度优先最后找顶点类

1、python3(非菱形,新式类)F-C-A-D-B-E

      python3(菱形,新式类)是广度优先,F-C-A-D-B-E-Z

2、python2(非菱形,新式类)F-C-A-D-B-E

      python2(非菱形,经典类)F-C-A-D-B-E

      python2(菱形,经典类),是深度优先,F-C-A-Z-D-B-E

      python2(菱形,新式类),是广度优先,F-C-A-D-B-E-Z

print(Chinese.mro()),查找属性的顺序就是根据这个顺序来找的

MixIn只是一种概念

class Fowl:  # 家禽类
    pass

# 只是一种命名规范,类名以MixIn结尾,代表混入一些功能,含义是鸡鸭鹅是家禽,但鸭鹅有游泳的工能
class SwimMixIn:
    def swimming(self):
        pass

class Chicken(Fowl):  # 鸡
    pass

class Duck(Fowl, SwimMixIn):  # 鸡
    pass

class Goose(Fowl, SwimMixIn):  # 鸡
    pass

super()

  严格意义上来说不是说是父类,而是Chinese.mro(),列表的下一个类

多态

父类的方法,子类都能调用(父类统一子类的所有方法),

class Car:
    def run(self):
        print("开始跑")


class Auto(Car):
    def run(self):
        super().run()
        print("Auto开始跑")


class Benzi(Car):
    def run(self):
        super().run()
        print("Benzi开始跑")


class tesla(Car):
    def run(self):
        super().run()
        print("tesla开始跑")


1、抽象基类(规范子类必须有什么东西,不推荐

子类Auto必须实现run方法

import abc


class Car(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def run(self):
        print("开始跑")


class Auto(Car):
    pass


auto = Auto()


"""
报错
Traceback (most recent call last):
  File "C:/Users/凉生/AppData/Roaming/JetBrains/PyCharm2021.2/extensions/混入功能.py", line 33, in <module>
    auto = Auto()
TypeError: Can't instantiate abstract class Auto with abstract methods run
"""

2、父类主动抛出异常,子类调用父类方法时会报错

class Foo:
    def f1(self, a):
        raise NotImplementedError("'子类必须实现此功能")


class Boo(Foo):
    def run(self, a):
        print(111)


b = Boo()
b.run(1)  # 不报错
b.f1(1)   # 报错

3、反射

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

    def run(self):
        print(self.name)
        return self.name

    def input_something(self):
        self.cmd = input(">>>")
        getattr(self, self.cmd, self.warning)()

    def warning(self):
        print("没有此方法", self.cmd)


human = Human("张三", 19)
print(hasattr(human, "age"))  # True
print(getattr(human, "age"))  # 19
print(getattr(human, "age1", 22))  # 22,指定默认值
print(getattr(human, "run"))  # <bound method Human.run of <__main__.Human object at 0x00000251DF4A81C0>>
print(getattr(human, "run")())  # 张三
human.input_something()

4、元类

type是元类

# 第1步
class_name = "Human"  # 类名
# 第2步
class_bases = (object,)  # 基类
# 第3步
class_dic = {}  # 执行子代码,产生名称空间
class_body = """
def __init__(self, name, age):
    self.name=name
    self.age=age

def speak(self):
    print(self)
"""

exec(class_body, {}, class_dic)
# 第4步
Human = type(class_name, class_bases, class_dic)  # type是元类
print(Human)  # 输出:<class '__main__.Human'>
obj = Human("张三", 12)
print(obj)  # 输出:<__main__.Human object at 0x000001CB1C1056D0>

自定义元类

# 自定义元类
class Mytype(type):
    def __init__(self, class_name, class_bases, class_dic):
        if "_" in class_name:
            raise NameError("类名不能有下划线")
        print("class_name:", class_name)
        print("class_bases:", class_bases)
        print("self.__bases__:", self.__bases__)
        print("class_dic:", class_dic)

    # 在 init方法前执行
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    # 定了这个方法,才能实例化对象,也就是  类型加(),例如  Chinese()
    def __call__(cls, *args, **kwargs):
        obj = cls.__new__(cls, *args, **kwargs)
        cls.__init__(obj , *args, **kwargs)
   


class Chinese(metaclass=Mytype):
    language = "Chinese"

    def __init__(self, name, age, sex, x):
        self.name = name
        self.age = age
        self.sex = sex
        self.x = x

    def speak(self):
        print(self.name + "在说" + self.language)


class BeiJingR(Chinese):
    pass
    print("这个类继承了Chinese, 她也是由自定义的Mytype创建的")
Mytype()

5、单例模式

1、模块(用的最多)

python的模块就是一个天然的单例模式

base.py文件定义类,实例化出一个对象obj

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


obj = Human("张大仙", 73)

在其他模块里导入这个对象obj,例如test.py里

from base import obj

2、类装饰器(面试问)

# 2、类装饰器(面试问)
def singleton_mode(func):
    obj = None  # 定义一个类,第一次是空,往后都会有值

    def wrapper(*args, **kwargs):
        nonlocal obj
        if not obj:  # 如果没有值,就实例化对象
            obj = func(*args, **kwargs)  # obj赋值
        return obj  # 返回对象

    return wrapper


@singleton_mode  # Human = singleton_mode(Human)
class Human:
    def __init__(self, name, age):
        self.name = name
        self.age = age


obj1 = Human("张大仙", 73)
obj2 = Human("张大仙", 73)
print(obj1 == obj2)  # True

3、类绑定方法(面试问)

# 3、类绑定方法(面试问)
class Human:
    obj = None

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

    @classmethod
    def get_obj(cls, *args, **kwargs):
        if not cls.obj:
            cls.obj = cls(*args, **kwargs)
        return cls.obj


obj1 = Human.get_obj("张大仙", 73)
obj2 = Human.get_obj("张大仙", 73)
print(obj1 == obj2)  # True

4、__new__方法(面试问)

# 4、__new__方法(面试问)
class Human:
    obj = None

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

    def __new__(cls, *args, **kwargs):
        if not cls.obj:
            cls.obj = super().__new__(cls)
        return cls.obj


obj1 = Human("张大仙", 73)
obj2 = Human("张大仙", 73)
print(obj1 == obj2)  # True

5、元类(面试问)

# 5、元类(面试问)
class MyType(type):
    obj = None

    def __call__(self, *args, **kwargs):
        if not self.obj:
            self.obj = super().__call__(*args, **kwargs)
        return self.obj


class Human(metaclass=MyType):
    def __init__(self, name, age):
        self.name = name
        self.age = age


obj1 = Human("张大仙", 73)
obj2 = Human("张大仙", 73)
print(obj1 == obj2)  # True


6、并发(面试问)

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值