python面向对象面试集锦(1-23)
Posted Jeff的技术栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python面向对象面试集锦(1-23)相关的知识,希望对你有一定的参考价值。
目录
- 1、简述面向对象三大特性
- 2、什么是鸭子类型?
- 3、super作用?
- 4、mro是什么?
- 5、什么是C3算法?
- 6、列举面向对象中带双下线的特殊方法?
- 7、单下划线与双下划线的作用?
- 8、实例变量和类变量的区别?
- 9、静态方法和类方法区别?
- 10、isinstance、issubclass和type的作用?
- 11、有用过with statement(语句)吗?它的好处是什么?
- 12、不可迭代的数据类型和可迭代的数据类型?
- 13、单例模式?singleton
- 14、python中如何判断一个对象是哦福可调用?
- 15、那些对象可以被调用?
- 16、队列、堆栈?
- 17、关于python类的继承?
- 18、用两个队列来实现一个栈?
- 19、类的加载顺序?
- 20、以下代码输出结果?
- 21、classmethod类方法和staticmethod静态方法?
- 22、@property装饰器?
- 23、栈与队列?
1、简述面向对象三大特性
封装:
封装指的是把一堆数据属性与方法数据放在一个容器中,这个容器就是对象。让对象可以通过 "." 来调用对象中的数据属性与方法属性。
继承:
继承指的是子类可以继承父类的数据属性与方法属性,并可以对其进行修改或使用。
多态:
在python中的多态指的是让多种类若具备类似的数据属性与方法属性,都统一好命名规范,这样可以提高开发者的代码统一性,使得调用者更方便去理解。
2、什么是鸭子类型?
鸭子类型是多态的一种表现形式
在python中不会强制性要求所有人的代码都统一规范,不统一也不会报错,若使用抽象类就会使python代码强制统一规范,这样不符合python动态语言的特性。所以让大家都自觉统一好规范,若大家的对象方法都类似的话就一种规范,只要长得像鸭子,就称之为鸭子类型。
3、super作用?
基类、超类
'''
使用super()可以在子类中调用父类的方法或属性, 可能你会说, 子类本来就可以调用父类中所有非私有的属性或方法,而我现在说的是, 当子类中实现了某个方法, 父类中也有这个方法, 当你调用这个方法时, 既想执行子类的又想执行父类的, 在这种情况下就可以使用super()
'''
4、mro是什么?
mro(): 会把当前类的继承关系列出来
'''
mro全称Method Resolution Order,指的是方法解析顺序。
方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。而搜索的顺序就是所谓的「方法解析顺序」。
'''
5、什么是C3算法?
# 答案
'''
C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。
'''
6、列举面向对象中带双下线的特殊方法?
类的内置方法(魔法方法):
凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法。
类的内置方法,会在某种条件满足下自动触发。
内置方法如下:
__new__: 在__init__触发前,自动触发。 调用该类时,内部会通过__new__产生一个新的对象。
__init__: 在调用类时自动触发。 通过产生的对象自动调用__init__()
__getattr__: 在 “对象.属性” 获取属性时,若 “属性没有” 时触发。
__getattribute__: 在 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发。
# 注意: 只要__getattr__ 与 __getattribute__ 同时存在类的内部,只会触发__getattribute__。
__setattr__:当 “对象.属性 = 属性值” , 添加或修改属性时触发
__call__ : 在调用对象 “对象 + ()” 时触发。 即:对象() 或者 类()()
__str__ : 在打印对象时触发。 # 注意: 该方法必须要有一个 “字符串” 返回值。
__getitem__: 在对象通过 “对象[key]” 获取属性时触发。
__setitem__: 在对象通过 “对象[key]=value值” 设置属性时触发。
__gt__,__lt__,__eq__:自定义比较对象大小双下:gt、lt、eq
__enter__: 进入文件时,开打文件时执行。返回值:self
__exit__: 退出文件时,报错中断、或者代码执行完时执行。 返回值:可以有返回值,是bool类型
__del__ : 手动删除时立马执行,或者程序运行结束时自动执行
使用场景:当你的对象使用过程中,打开了不属于解释器的资源;例如,文件,网络端口
__slots__:原理,给对象声明只有某些属性,从而删除不必要的内存,不能添加新属性
使用场景:1.优化对象内存 2.限制属性数量
7、单下划线与双下划线的作用?
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
***原理: 替换变量名称 方法名 替换为:_类名__方法名***
'''
"单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量。
"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
'''
8、实例变量和类变量的区别?
'''
类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象;
'''
9、静态方法和类方法区别?
'''
Python的类就是个语法糖。一个函数写在类里面和写在类外面没有区别,唯一的区别就是参数,所谓实例方法就是第一个参数是self,所谓类方法就是第一个参数是class,而静态方法不需要额外的参数,所以必须区分。
'''
10、isinstance、issubclass和type的作用?
issubclass 判断是否是谁的子类
isinstance判断一个对象是否是另一个类的实例化
type获取数据类型
'''
type和isinstance都可以判断变量是否属于某个内建类型
type只接收一个参数,不但可以判断变量是否属于某个类型,而且可以得到参数变量未知的所属的类型;而isinstance只能判断是否属于某个已知类型,不能直接得到变量未知的所属的类型
'''
11、有用过with statement(语句)吗?它的好处是什么?
# 答案
'''
with语句会在嵌套的代码执行之后,自动关闭文件。这种做法的还有另一个优势就是,无论嵌套的代码是以何种方式结束的,它都关闭文件。如果在嵌套的代码中发生异常,它能够在外部exception handler catch异常前关闭文件。如果嵌套代码有return/continue/break语句,它同样能够关闭文件。
'''
12、不可迭代的数据类型和可迭代的数据类型?
可迭代:dict、set、str
不可迭代:object
13、单例模式?singleton
单例模式:一份数据,重复使用。(一个地址),节约内存空间
单例模式: (面试让你手撸,一定要背下来。)
1.通过classmethod 类绑定方法
2.通过装饰器实现
3.通过__new__实现
4.通过导入模块时实现
5.通过元类实现。
# 答案:
1.__new__
class Borg(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
ob = super(Borg, cls)
cls._instance = ob.__new__(cls, *args, **kwargs)
return cls._instance
class MyClass(Borg):
def __init__(self):
self.a = 1
2.共享属性
class Borg2(object):
_state = {}
def __new__(cls, *args, **kwargs):
ob = super(Borg2, cls).__new__(cls, *args, **kwargs)
ob.__dict__ = cls._state
return ob
class MyClass(Borg2):
def __init__(self):
self.a = 1
3.装饰器
def singleton(cls, *args, **kwargs):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class MyClass(object):
def __init__(self):
self.a = 1
4.import方法
# mysingleton .py
class MyClass(object):
def __init__(self):
self.a = 1
s_myclass = MyClass()
from mysingleton import s_myclass
s_myclass.a
14、python中如何判断一个对象是哦福可调用?
# python 中如何判断一个对象是否可调用
def func():
pass
print(callable(func)) # True
15、那些对象可以被调用?
# 哪些对象可以是可调用对象
1.类对象
2.所有带有_call_()方法的对象
# 如何定义一个类,使其对象本身就是可调用对象
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法call()。
16、队列、堆栈?
queue:队列模块
joinablequeue:可等待的队列模块
队列(FIFO):先进先出(买包子,先排队先买)
堆栈(FILO):先进后出(衣柜放衣服,先放进去,后拿出来)
from multiprocessing import Queue
q = Queue(5) # 生成队列对象,括号内的数字表示 这个队列最大储存数
q.put(1) # 往队列中添加数据1,
当队列满了,再放数据,不会报错,程序原地等待(阻塞态),等待有位置放值
q.get() # 取值,因为先进先出,所以先取第一个值
当队列取完之后,再次取值,程序原地等待(阻塞态),等待有值取
q.get_nowait() # 取值不等待(阻塞),没有了直接报错
q.put_nowait() # 添加值不等待(阻塞),满了直接报错
q.full() # 判断队列是否满了(bool值)
q.empty() # 判断队列是否为空(bool值)
q.join() # 等待
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。
可以理解为,每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。
17、关于python类的继承?
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类(super),新建的类称为派生类或子类
18、用两个队列来实现一个栈?
# 答案:
class StackWithTwoQueues(object):
#定义两个空队列
def __init__(self):
self.queue1 = []
self.queue2 = []
#入栈
def push(self, item):
self.queue1.append(item)
#出栈
def pop(self):
if len(self.queue1) == 0:
return(None)
while(len(self.queue1) != 1):
self.queue2.append(self.queue1.pop(0))
self.queue1, self.queue2 = self.queue2, self.queue1
return (self.queue2.pop())
#test
if __name__ == '__main__':
ss = StackWithTwoQueues()
list = [0, 1, 2, 3, 4]
for i in range(5):
ss.push(list[i])
print(list)
for i in range(5):
print(ss.pop(), ',', end = '')
#output
#[0, 1, 2, 3, 4]
#4, 3, 2, 1, 0
19、类的加载顺序?
1、 类对象
2、 实例对象
3、 self变量名称问题
4、 类属性、实例变量、局部变量
5、 类方法
6、 实例方法
7、 类方法与实例方法相互调用
8、 静态方法
9、 继承时三类方法的影响
20、以下代码输出结果?
class Parent:
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Child1.x = 3
print(Parent.x, Child1.x, Child2.x)
# 答案
'''
1 1 1
1 2 1
1 3 1
'''
解释:优先使用自己的x,如果自己没有则使用继承的
21、classmethod类方法和staticmethod静态方法?
classmethod:类绑定方法
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。直接类.方法
class Dog():
def eat(self):
print('狗狗吃饭饭。。。')
class Pig():
@classmethod # 将此方法对象绑定
def eat(self):
print('猪猪看电视。。。')
# 对象绑定方法,需要实例化出一个对象
keji = Dog()
keji.eat()
# 类绑定方法,不需要对象,直接通过类
zhu = Pig.eat()
staticmethod:非绑定方法(静态方法)
- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
22、@property装饰器?
装饰器:为了调用方式一致,方便使用者
@property首先创建一个age对象,所以@setter、@deleter要加函数名
:这里的age是装饰方法的名称
@property(获取私有) :把一个方法伪装成普通属性,通常函数名和属性名保持一致(方便使用者调用)
@函数名.setter(修改私有):函数名和属性名保持一致
@函数名.deleter(控制删除):
class A:
def __init__(self, name, age):
self.name = name
self.__age = age
@property # 获取属性时,触发下面
# 获取伪装成普通属性,通常函数名伪装成属性名
def age(self):
return self.__age
@age.setter # 修改属性时,触发下面
def age(self, new_age):
self.__age = new_age
print('修改成功')
@age.deleter # 删除属性时,触发下面
def age(self):
del self.__age
print('删除成功,已经没有了')
# 查看
jeff = A('jeff', 50)
print(jeff.age) # 50
# 修改
jeff.age = '100'
print(jeff.age) # 修改成功 100
# 删除
del jeff.age
print(jeff.age) # 报错,删除成功,已经没有了
23、栈与队列?
编程实现一个先进先出的队列,能够指定初始化队列大小,以及enqueue,dequeue,isempty,isfull四种方法?
使用方法如下:
s = Queue(2) # 初始化一个大小为 2 的队列
s.is_empty() # 初始化后, 队列为空, 返回 True
s.enqueue(1) # 将 1 加入队列
s.enqueue(2) # 将 2 加入队列
s.isfull() # 加入了两个元素, 队列已满, 返回 True 6. s.dequeue() # 移除一个元素, 返回 1
s.dequeue() # 移除一个元素, 返回 2
s.is_empty() # 队列已经为空, 返回 True
以上是关于python面向对象面试集锦(1-23)的主要内容,如果未能解决你的问题,请参考以下文章