python|面向对象(二)面试重点

面向对象(二)记忆部分

一、新式类和经典类

区别:继承了python内置类的时候,才是新式类其他的都是经典类

经典类 :通过type查看到的实例类型都叫做instance

类和实例之间只能够通过__class__属性进行关联

新式类 :通过type查看到的实例类型就是类名

[root@wh ~]# python2
Python 2.7.5 (default, Nov 16 2020, 22:23:17
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on l
Type "help", "copyright", "credits" or "lice
>>> class A:pass
...
>>> a = A()
>>> type(a)
<type 'instance'>
>>> a.__class__
<class __main__.A at 0x7fa8732ee258>
---------------------------------------------
[root@wh ~]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:pass
...
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class '__main__.A'>

多重继承顺序的区别

经典类:深度优先算法,从左至右,一条路走到底

新式类:c3算法

class A:
    def test(self):
        print("from A")

class B(A):
    def test(self):
        print("from B")

class C(A):
    def test(self):
        print("from C")

class D(B):
    def test(self):
        print("from D")

class E(C):
    def test(self):
        print("from E")

class F(D,E):
    # def test(self):
    #     print("from F")
    pass

f = F()
f.test()
#逐个注释进行验证
#经典类:F--> D --> B --> A --> E --> C
#新式类:F--> D --> B --> E --> C --> A
#c3算法:
#  首先将自身类加入到本序列,然后对继承序列的元素依次判断
#  若某元素不在其他序列或者它是所有继承序列的第一个,那么就把这个元素提取到本序列

二、实例方法、静态方法和类方法

属性:对象的描述信息
静态属性 – 类属性
普通属性 – 实例属性

方法:对象的行为
实例方法
静态方法
类方法

class A():
    name = "changsha" #静态属性
    def __init__(self):
        self.country = "china" #普通属性
    #普通(实例)方法
    #接收的第一个参数,就代表实例本身
    def normal_method(self,name):
        print("nomal:")
        print(self.name,name)

    #使用classmethod修饰的方法,称为类方法
    #接收的第一个参数是类
    @classmethod
    def class_method(cls,name):
        print("class_method:".center(30,'*'))
        print(type(cls), cls)
        print(cls.name, name)

    #使用staticmethod修饰的方法,称为静态方法
    #可以接受参数也可以不接受参数,参数不代表实例也不代表类
    @staticmethod
    def static_method(name):
        print("static_method:")
        print(A.name, name)

a = A()

#通过实例调用类方法,静态方法,实例方法 都可以
a.normal_method("nomalmethod")
a.class_method("classmethod")
a.static_method("staticmethod")

#通过类去调用类方法、静态方法、实例方法
#通过类调用实例方法的时候,一定要传一个实例进去
A.normal_method(a,"normal_method")
A.class_method("classmethod")
A.static_method("staticmethos")

三、 python的下划线

class Parent:
    '''
    this is parent
    class
    '''
    tmp = "tmp" #普通成员
    _min = 1    #保护成员
    __max = 10  #私有成员

    def __init__(self):
        self.name = "sc"
        self._age = 4
        self.__desc = "it" #--> self._Parent__desc

    def __make(self):
        print("这是一个私有方法")
        print(self.__desc)  #--> self._Parent__desc

    def _protectmake(self):
        print("这是一个保护方法")

    def show(self):
        print(self.__max, self.__desc)
        print("这是一个普通方法")

class Child(Parent):
    def show(self):
        print(self.__max)

#Parent
#类属性  tmp, _min, __max
#实例属性 name, _age, __desc
#方法    __make,  _protectmake, show
p = Parent()
c1 = Child()

# 访问普通成员和保护成员
print(p.tmp, c1.tmp)
print(p._min, c1._age, c1._min)
p._protectmake()
c1._protectmake()

#访问私有成员 __max   __desc   __make

# print(p.__max)
#AttributeError: 'Parent' object has no attribute '__max'

# print(p.desc)
#'Parent' object has no attribute 'desc'

p.show() #是可以访问到的,类的内部会将self.__max 解释成 self._Parent__max

# c1.show()
#'Child' object has no attribute '_Child__max'

#查看实例空间有哪些属性
print(p.__dict__)
#{'name': 'sc', '_age': 4, '_Parent__desc': 'it'}

# print(p.__max)
#AttributeError: 'Parent' object has no attribute '__max'

print(p._Parent__max) #python中的私有其实是一种伪私有,就是将双下划线开头的标识符改了一个名字--》_类名__标识名
#10

p.__make()
# 这是一个私有方法
# it

p = Parent()
c1 = Child()
-----------------------
#python中常用的下划线
#查看对象的属性和方法
print(dir(p))
print(p.__dir__())

#文档注释
print(Parent.__doc__)
#print(help(Parent))

# 查看对象和类空间
print(p.__dict__)
print(Parent.__dict__)

#查看对象属于哪个类
print(p.__class__)
#<class '__main__.Parent'>

#类名
print(Parent.__name__)
#Parent

#查看父类
print(Child.__bases__)
#(<class '__main__.Parent'>,)

#对象的hash值
print(c1.__hash__())
#3500883

四、 常用的魔术方法

什么是魔术方法?

在python中,所有以双下划线__包起来的方法,统称为 Magic Method(魔术方法)
它是一种特殊的方法,普通方法需要调用,而魔术方法不需要调用就可以自动执行

魔术方法在类或对象的某些事件触发后会自动执行,让类具有神奇的"魔力"
如果希望根据自己的程序定制自己特殊功能的类,那么就需要对这些方法进行重写

Python中常用的运算符、for循环、以及类操作等都是运行在魔术方法之上的

4.1 newinitdel、__call__方法的使用

# 构造函数(__new__/__init__)
      __new__:创建实例
      __init__:初始化实例
# 析构函数(__del__)
      在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,如关闭数据库连接,关闭打开的临时文件
# 调用方法(__call__)
      把类实例化后的对象当做函数来调用的时候自动被调用
class ATM:
    def __del__(self):
        print("执行del")
    def __call__(self, name, age):
        print(f"my name id {name}, my age is {age}")

#a = ATM()
#执行del
#程序执行完了,会释放内存,删除实例a,并执行__del__

a = ATM() #程序没有执行完,不会执行__del__
del a     #删除实例a,然后执行__del__
print("删除a")
# 执行del
# 删除a

# __call__
a = ATM()
a("sc",4) #有__call__方法,实例可以像函数一样进行调用

4.2 str 、__repr__方法的使用

# __str__ __repr__
# 返回对象的描述信息
# __str__ 默认调用的就是__repr__
# __str__ 给用户看的
# __repr__ 更加官方的说明,给程序员看的(交互式环境)
>>> class A:
...     def __str__(self):
...         return "str...A"
...     def __repr__(self):
...         return "repr...A"
...
>>> a = A()
>>> print(a)
str...A
>>>
>>> result = str(a)
>>> print(result)
str...A
>>> a
repr...A

>>> class A:
...     def __repr__(self):
...         return "repr...A"
...
>>> a = A()
>>> print(a)
repr...A
>>> a
repr...A
应用:
try:
    a = []
    print(a[1])
except IndexError as e:
    print(e)
#list index out of range

#自定义异常类
class error(Exception):
    def __str__(self):
        return "list内元素长度超过10个"

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
try:
    if len(lst) > 10:
        raise error
except error as e:
        print(e)

#方法二
class error(Exception):
    def __str__(self):
        return "list内元素长度超过10个"
e = error()
try:
    lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    if len(lst) > 10:
        raise IndexError
except IndexError:
        print(e)

----------------------
class error2(Exception):
    def __str__(self):
        return "消息长度小于8"

message_str = input("请输入消息:")
try:
    if len(message_str) < 8:
        raise error2
except error2 as a:
    print(a)
------------------------
import time

class Tst(object):
    def __init__(self, n):
        self.n = n
        self._created_time = time.time()

    def __str__(self) -> str:
        # 以友好的方法输出对象
        return f"Tst:{self.n}"

    def __repr__(self) -> str:
        # 正式输出 => 以友好的方法输出对象
        return f"<Tst:{self.n}>"

    # def __lt__(self, other):
    #     return self._created_time < other._created_time

t1 = Tst(1)
time.sleep(1)
t2 = Tst(2)
time.sleep(1)
t3 = Tst(3)
time.sleep(1)

print(t1)
# <__main__.Tst object at 0x0000000001DC8430> 
#  => __str__ => Tst:1

mylist = [t3, t1, t2]
print(mylist)
# 定义了__repr__ => [<Tst:3>, <Tst:1>, <Tst:2>]

# 请按创建时间给mylist排序:mylist排序结果 =》 [t1, t2, t3]

mylist = sorted(mylist, key=lambda x: x._created_time)
# mylist = sorted(mylist)  # 本质元素和元素之间 <
# 给类添加一个__lt__方法

print(mylist)  # => [<Tst:1>, <Tst:2>, <Tst:3>]

4.3 getitemsetitem、__delitem__方法的使用

让对象以字典的形式去设置或者获取参数

用在设置或者配置属性的时候使用

class A:
    def __init__(self):
        self.data = {}

    def __getitem__(self, key):
        print("get data:")
        return self.data.get(key,0) #获取value值,如果没有,默认值为0

    def __setitem__(self, key, value):
        print("set data:")
        self.data[key] = value

    def __delitem__(self, key):
        print("delete data:")
        del(self.data[key])
a = A()
a["key"] = "value"  #调用__setitem__
#set data:
print(a["key"])     #调用__getitem__
# get data:
# value

a["k1"] = "v1"
#set data:
a["k2"] = "v2"
#set data:
print(a["k3"])
#get data:
#0
print(a.data)
#{'key': 'value', 'k1': 'v1', 'k2': 'v2'}

del a["key"]  #调用__delitem__
print(a.data)
# delete data:
# {'k1': 'v1', 'k2': 'v2'}

4.4 add、__gt__方法的使用

# 定义对象的加号行为
import time
class A:
    def __init__(self, num):
        self.time = time.time()
        self.num = num

    def __add__(self, x):
        print("this is add")
        return self.num + x

    def __gt__(self, other):
        print("this is gt")
        return self.time > other.time  #比较创建实例的时间和其他实例的创建时间
a1 = A(5)
b = a1 + 6  #调用__add__
#this is add
print(b)
#11

time.sleep(1)
a2 = A(4)
print(a1 > a2)  #调用__gt__
# this is gt
# False

五、python自省

hasattr、setattr、getattr、delattr

#python自省
print(hasattr(math, "xx"))   #判断math有没有xx属性
print(setattr(math, "xx", 1))#设置math的xx属性为1
print(getattr(math, "xx"))   #获取math的xx属性
print(delattr(math, "xx"))   #删除math的xx属性

练习:根据choose的值,调用不同的函数,按‘q’退出

class A:
    name = "sc"
    def func1(self):
        print("i am func1")
    def func2(self):
        print("i am func2")
a = A()
# print(dir(a.func1()))
# print(dir(a.name))
while 1:
    choose = input("please input function:")
    if choose == 'q':
        break
    elif hasattr(a,choose):
        result = getattr(a,choose)
        if hasattr(result, "__call__"):
            result()
        else:
            print(result)
    else:
        print("没有这个函数")

六、python元类

创建类的类,称之为元类,type是最上层的元类

# type:创建类
class A:
    pass
a = A()
print(type(a))
# <class '__main__.A'>
print(type(A))
# <class 'type'>
用type手动创建类
# 普通定义类
class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print("i am eating...")
# 用type创建类
# 第一个参数:类名  字符串
# 第二个参数:继承关系  元组
# 第三个参数:方法和属性  字典
def init(self, name):
    self.name = name
def eat(self):
    print("i am eating...")
Animal = type("Animal",(object,),{"__init__":init, "eat":eat})
a1 = Animal("sc1")
print(a1.name)
#sc1
元类的使用

拦截类的创建,实现自定义类

class MyMate(type):
    def __new__(cls, name, bases, attrs):
        if "ufo" not in attrs:
            raise TypeError("必须设置ufo属性")
        return type.__new__(cls, name, bases, attrs)


class A(metaclass = MyMate):
    ufo = "sc"

print(A)
type object
面向对象里面有两种关系
1.继承关系 object是所有类的父类,是最顶层的类
2.创建关系 实例与类的关系  type是最顶层的类

print(type(object))
# <class 'type'>
print(type(type))
# <class 'type'>
print(object.__bases__)
# ()
print(type.__bases__)
# (<class 'object'>,)

object = type(object)
#相当于一种鸡生蛋,蛋生鸡的关系  先有鸡还是先有蛋

七、抽象基类

定义了接口规范,子类必须实现抽象基类父类里的抽象方法(@abstractmethod),不是抽象方法可以不用实现

抽象基类不能实例化

from abc import ABC, abstractmethod
class Animal(ABC):

    #定义抽象方法
    @abstractmethod
    def eat(self):
        pass

    def drink(self):
        pass

class Dog(Animal): #子类必须实现父类里的抽象方法
    #pass  #会报错,子类里面没有实现抽象方法eat

    def eat(self):
        print("dog is eating...")

dog = Dog()

#a = Animal()
#抽象基类不能进行实例化
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值