0. 什么是类?什么是对象?

类:具有相同属性和技能的一类事物
对象:就是类的具体表现,具体是实例

1. 面向对象为什么有继承?

  • 优化代码,节省代码
  • 提高代码的复用性.
  • 提高代码的维护性.
  • 让类与类之间发生关系.

2. 关于组合?

让对象与对象发生关系

3. 子类中即实现父类的方法,又实现自己的方法?

1. super().父类方法名(参数(自传self))
    2. 父类名.父类方法名(参数)

4. 什么是新式类与经典类?

  • 继承object类的类都叫新式类. python3x中所有的类默认都继承object,python3x中全部都是新式类.
    广度优先
  • 经典类:不继承object类就是经典类. Python2x 默认是经典类,可以让其继承object变成新式类.
    深度优先
  • 深度优先,广度优先: 只能是继承两个类的情况.
  • 继承分类为单继承,多继承。又可以分类为新式类与经典类

5. 面向对象的三大特性是什么?

  • 继承
  • 多态
  • 封装

6. 怎么查询类的继承顺序?

查询类的继承顺序:类名.mro()

7. 从类名角度分析,操作获取数据的方法?

# 1.操作静态字段
    # 1 查询类中的全都内容
     __dict__
    # 2. 万能的点
    # 3. 增删改查
# 2.操作类的方法(除了类方法,静态方法需要类名调用之外。剩下的方法都要对象调用)

8. 从对象角度分析,操作获取数据的方法?

# 操作静态字段
    # 1. 查询对象空间全部的内容 print(obj.__dict__) {'name': 'ALEX', 'age': 100}
    # 2. 万能的点
# 操作类的方法
    # obj.func() 对象.方法名

9. 实例化对象的三个基本步骤?

# 1. 创建了一个对象空间,实例空间
# 2. 自动执行 __init__ 方法,并将我的对象空间传给self
# 3. 执行具体的 __init__ 代码,给对象空间封装属性
  • 1.开辟一个空间,属于对象的
  • 2.把对象的空间传给self,执行init
  • 3.将这个对象的空间返回给调用者

10. 面向对象中super的作用?

  • 在子类中调用父类的方法.

11. 经典习题1?

class A:
    name = []
p1 = A()
p2 = A()
p1.name.append(1)
# p1.name,p2.name,A.name 分别是什么?
print(p1.name) #[1]
print(p2.name) #[1]
print(A.name) #[1]

12. 什么是抽象类?

  • python 没有接口这个概念
  • 接口类,抽象类: 制定一个规范.
  • 强制制定一个规范,凡是继承我的类中必须有某个方法,如果没有,实例化对象的时候就会报错
class Payment(metaclass=ABCMeta):  # 抽象类(接口类):
     @abstractmethod
     def pay(self): pass  # 制定了一个规范
     @abstractmethod
     def func(self):pass

13. 什么是多态?

  • python面向对象的三大特征之一:
  • 多态: python处处是多态.
  • java :强类型语言 - python 弱类型语言
  • python 不管什么类型,传入函数,封装到对象中都可以.
  • python没有多态?他有什么? 他有鸭子类型.
  • 鸭子类型 : 看着像鸭子,他就是鸭子.
  • 这些类 都互称为鸭子.鸭子类型其实是一种统一化设计的思想

14 什么是封装?

  • 广义的封装: 实例化一个对象,给对象空间封装一些属性.给类中封装静态字段…
  • 狭义的封装: 私有制.

15 面向对象中的成员有哪些?

私有成员有:
  • 私有静态字段 ----实例化对象不能访问私有静态字段+类名不能访问私有静态字段(对于私有静态字段,只能在本类中内部访问,类的外部,派生类均不可访问.)
# 可以访问,但是工作中千万不要用.
# print(A._A__age)
  • 私有方法 ----类的内部可以访问,类外部不能访问,类的派生类也不能访问
  • 私有对象属性
普通成员有:
  • 静态变量(静态字段)
  • 对象属性(普通字段)
  • 属性
  • 普通方法
特殊成员有:
  • 特殊方法
  • 类方法
  • 静态方法
class A:

    company_name = 'xxxx公司'  # 静态变量(静态字段)
    __iphone = '1353333xxxx'  # 私有静态变量(私有静态字段)


    def __init__(self,name,age): #特殊方法

        self.name = name  #对象属性(普通字段)
        self.__age = age  # 私有对象属性(私有普通字段)

    def func1(self):  # 普通方法
        pass

    def __func(self): #私有方法
        print(666)


    @classmethod  # 类方法
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print('类方法')

    @staticmethod  #静态方法
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print('静态方法')

    @property  # 属性
    def prop(self):
        pass

16.经典面试题2?

class Parent:
    def __func(self):
        print('in Parent func')

    def __init__(self):
        self.__func()

class Son(Parent):
    def __func(self):
        print('in Son func')
son1 = Son()
# 运行结果是?

17 面向对象中,如何将方法变成属性?

将方法伪装成一个属性,代码上没有什么提升,只是更合理.
@property ***
@属性名.setter **
@属性名.deleter *

18 什么是类方法?

  • 类方法: 通过类名调用的方法,类方法中第一个参数约定俗称cls,python自动将类名(类空间)传给cls.
  • 对象调用类方法,cls 得到的是类本身.
类方法的应用场景:
  • 类中 有些方法是不需要对象参与
  • 对类中的静态变量进行改变.要用的类方法
  • 继承中,父类得到子类的类空间

19 什么是静态方法?有什么作用?

静态方法使用的关键字是@staticmethod,通过在方法前追加此装饰器该方法就属于一个静态方法,静态方法个人理解为它既不依赖实例对象也不依赖于类,它只是需要一个载体即可,所以无论是通过类对象直接调用还是实例对象进行调用都是可以的,需要注意的是在静态方法中无法使用实例属性和方法。所以在日常过程中如果有一个方法实现的功能比较独立的时候就可以考虑使用静态方法实现

作用
  • 代码块.清晰
  • 复用性.

20 ‘==’ 与 ‘is’有什么区别与联系?

  • ‘==’值相等,值运算
  • is 内存地址相等, 身份运算
  • is要求更苛刻 —不仅要求值相等,还要求内存地址相同

21 isinstance() 与 issubclass()?

  • isinstance()判断对象所属类型,包括继承关系
  • issubclass() 判断类与类之间的继承关系

22 什么是反射?

  • 用字符串数据类型的变量名来访问这个变量的值
  • 反射的方法: getattr hasattr setattr delattr
反射的应用场景
  • 类(可以从类的 静态属性(字段)类方法静态方法中拿到对应的值)
  • 对象(可以从对象中 对象属性 方法 中拿到对应的值)
  • 模块
  • 反射自己模块中的内容
# 类名.名字
    # getattr(类名,'名字')
# 对象名.名字
    # getattr(对象,'名字')
# 模块名.名字
    # import 模块
    # getattr(模块,'名字')
# 自己文件.名字
    # import sys
    # getattr(sys.modules['__main__'],'名字')

23. ——名字——?

  • 类中的特殊方法
  • 双下方法
  • 魔术方法 magic method
  • 内置方法
    类中的每一个双下方法都有它自己的特殊意义
# __call__ 相当于 对象() flask框架
# __len__  len(obj)
# __new__  特别重要   开辟内存空间的 类的构造方法
# __str__  str(obj),'%s'%obj,print(obj)

# 所有的双下方法 没有 需要你在外部直接调用的
# 而是总有一些其他的 内置函数 特殊的语法 来自动触发这些 双下方法
# __new__    # ==> 构造方法
	# 1.开辟一个空间,属于对象的
	# 2.把对象的空间传给self,执行init
	# 3.将这个对象的空间返回给调用者
# __init__  # ==> 初始化方法
# print一个对象相当于调用一个对象的__str__方法
# str(obj),相当于执行obj.__str__方法
# '%s'%obj,相当于执行obj.__str__方法

24 什么是单例类?

  • 如果一个类 从头到尾只能有一个实例,说明从头到尾之开辟了一块儿属于对象的空间,那么这个类就是一个单例类
class Single:
    __ISINCTANCE = None
    def __new__(cls, *args, **kwargs):
        if not cls.__ISINCTANCE:
            cls.__ISINCTANCE = object.__new__(cls)
        return cls.__ISINCTANCE
    def __init__(self,name,age):
         self.name = name
         self.age = age
       

s1 = Single('alex',83)
s2 = Single('taibai',40)

25. 什么是析构方法?

  • 构造方法 申请一个空间
  • 析构方法 释放一个空间之前执行
  • 某对象借用了操作系统的资源,还要通过析构方法归还回去 : 文件资源 网络资源
class A:
     def __del__(self):
         # 析构方法 del A的对象 会自动触发这个方法
         print('执行我了')
 a = A()
 del a  # 对象的删除 del
 print(a)

26.item系列与attr系列

  • __setitem__赋值方法,在进行obj[name]=value时,会触发执行该方法
  • __delitem__删除方法,在进行del obj[name],就会触发执行该方法
  • __getitem__查询方法,在进行读取obj[name]的值时,就会触发执行该方法
  • 把对象操作属性模拟成字典的格式
    item系列与attr系列都是方法,都是在定义阶段,而反射是内置函数,是在使用阶段
    item系列是在对象进行字典形式的操作时,在会执行相应方法,而attr系列是不同的,
  • item系列 和对象使用 [ ] 访问值有联系
  • 有一些特殊的方法,要求对象必须实现__getitem__/__setitem__才能使用
class B:
    def __getitem__(self, item):
        return getattr(self,item)
    def __setitem__(self, key, value):
        setattr(self,key,value*2)
    def __delitem__(self, key):
        delattr(self,key)
b = B()
# b.k2 = 'v2'
# print(b.k2)
b['k1'] = 'v1'  # __setitem__
print(b['k1'])  # __getitem__
del b['k1']     # __delitem__
print(b['k1'])

27.hash方法?

  • hash是一个算法 也是python中的一个内置函数
  • 能够把某一个要存在内存里的值通过一系列计算, 保证不同值的hash结果是不一样的
  • 对同一个值在多次执行python代码的时候hash值是不同
  • 但是对同一个值 在同一次执行python代码的时候hash值永远不变

28.经典面试题3?

员工管理系统
对象的属性 : 姓名 性别 年龄 部门
内部转岗 python开发 - go开发
姓名 性别 年龄 新的部门
600个员工
如果几个员工对象的姓名和性别相同,这是一个人。请对这600个员工做去重?

class Employee:
    def __init__(self,name,age,sex,partment):
        self.name = name
        self.age = age
        self.sex = sex
        self.partment = partment
    def __hash__(self):
        return hash('%s%s'%(self.name,self.sex))
    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex:
            return True
employ_lst = []
for i in range(200):
    employ_lst.append(Employee('alex',i,'male','python'))
for i in range(200):
    employ_lst.append(Employee('wusir',i,'male','python'))
for i in range(200):
    employ_lst.append(Employee('taibai', i, 'male', 'python'))

# print(employ_lst)
employ_set = set(employ_lst)
for person in employ_set:
    print(person.__dict__)

#{'name': 'alex', 'age': 0, 'sex': 'male', 'partment': 'python'}
#{'name': 'taibai', 'age': 0, 'sex': 'male', 'partment': 'python'}
#{'name': 'wusir', 'age': 0, 'sex': 'male', 'partment': 'python'}
#进程已结束,退出代码0
  • set集合的去重机制 : 先调用hash,再调用eq,eq不是每次都触发,只有hash值相等的时候才会触发

28 模块的分类?

  • 内置模块
    安装python解释器的时候跟着装上的那些方法
  • 第三方模块/扩展模块
    没在安装python解释器的时候安装的那些功能
  • 自定义模块
    你写的功能如果是一个通用的功能,那你就把它当做一个模块

29.什么是模块?

  • 有的功能开发者自己无法完成,这样的话需要借助已经实现的函数\类来完成这些功能
  • 你实现不了的功能都由别人替你实现了
    # 操作系统打交道
    # 和时间
    # 1000取随机数
    # 压缩一个文件
    # 和网络通信
  • 别人写好的一组功能 文件夹/py文件/C语言编译好的一些编译文件
    # 分类 管理方法
    # 节省内存
    # 提供更多的功能

30.为什么要有模块?模块怎么用?在哪儿用?

# 分类 管理方法
# 节省内存
# 提供更多的功能
# import 导入 # 要导入一个py文件的名字,但是不加.py后缀名
# import这个语句相当于什么??? import这个模块相当于执行了这个模块所在的py文件
# 模块可以被多次导入么? 一个模块不会被重复导入,即使重复写了多次也只执行一次
# 模块的名称必须满足变量的命名规范,一般情况下 模块都是小写字母开头的名字
# 模块的重命名 import my_module as m
# 在import之后再修改这个被导入的模块,程序是感知不到的
# 如何反射本模块的变量:getattr(sys.modules[__name__],'要反射的变量名')
# 在编写py程序的时候,所有不在函数和类中封装的内容都应该写在 if __name__ == '__main__':下面
# sys.models 存储了所有导入的文件的名字和这个文件的内存地址
# 在模块的导入中,不要产生循环引用问题,如果发生循环导入了就会报错,就会发现明明写在这个模块中的方法,却显示找不到
#  * 和 __all__ 的相关性      __all__ 可以控制*的导入情况
# PEP8规范
	# 所有的模块导入都应该尽量放在这个文件的开头
	# 模块的导入也是有顺序的
		# 先导入内置模块
        # 再导入第三方模块
        # 最后导入自定义模块