Python⾯试题——⾯向对象题
1、简述⾯向对象的三⼤特性。
封装: 封装指的是把⼀堆数据属性与⽅法数据放在⼀个容器中,这个容器就是对象。让对象可以通过 “.” 来调⽤对象中的数据属性与⽅法属性。
继承: 继承指的是⼦类可以继承⽗类的数据属性与⽅法属性,并可以对其进⾏修改或使⽤。
多态: 在python中的多态指的是让多种类若具备类似的数据属性与⽅法属性,都统⼀好命名规范,这样可以提⾼开发者的代码统⼀性,使得调⽤者更⽅便去理解。
2、什么是鸭⼦模型?
在python中不会强制性要求所有⼈的代码都统⼀规范,不统⼀也不会报错,若使⽤抽象类就会使python代码强制统⼀规范,这样不符合python动态语⾔的特性。所以让⼤家都⾃觉统⼀好规范,若⼤家的对象⽅法都类似的话就⼀种规范,只要长得像鸭⼦,就称之为鸭⼦类型。
3、super 的作⽤?
使⽤super()可以在⼦类中调⽤⽗类的⽅法或属性, 可能你会说, ⼦类本来就可以调⽤⽗类中所有⾮私有的属性或⽅法,⽽我现在说的是,当⼦类中实现了某个⽅法, ⽗类中也有这个⽅法, 当你调⽤这个⽅法时, 既想执⾏⼦类的⼜想执⾏⽗类的, 在这种情况下就可以使⽤super() 4、mro 是什么?
mro全称Method Resolution Order,指的是⽅法解析顺序。 ⽅法调⽤时就需要对当前类和基类进⾏搜索以确定⽅法所在的位置。⽽搜索的顺序就是所谓的「⽅法解析顺序」。
5、什么是 c3 算法?
C3算法最早被提出是⽤于Lisp的,应⽤在Python中是为了解决原来基于深度优先搜索算法不满⾜本地优先级,和单调性的问题。
本地优先级:指声明时⽗类的顺序,⽐如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查A类,然后再查B类。
单调性:如果在C的解析顺序中,A排在B的前⾯,那么在C的所有⼦类⾥,也必须满⾜这个顺序。
6、列举⾯向对象中带双下划线的特殊⽅法。
#__setattr__: 添加/修改属性会触发它的执⾏
#__delattr__: 删除属性的时候会触发
#__getattr__: 只有在使⽤点调⽤属性且属性不存在的时候才会触发
#__getattribute__: 不管是否存在,我都会执⾏
7、双下划线和单下划线的区别?
“单下划线” 开始的成员变量叫做保护变量,意思是只有类对象和⼦类对象⾃⼰能访问到这些变量。
“双下划线” 开始的是私有成员,意思是只有类对象⾃⼰能访问,连⼦类对象也不能访问到这个数据。
8、实例变量和类变量的区别?
类变量是所有对象共有,其中⼀个对象将它值改变,其他对象得到的就是改变后的结果;⽽实例变量则属对象私有,某⼀个对象将其值改变,不影响其他对象;
9、静态⽅法和类⽅法区别?
Python的类就是个语法糖。⼀个函数写在类⾥⾯和写在类外⾯没有区别,唯⼀的区别就是参数,所谓
实例⽅法就是第⼀个参数是self,所谓类⽅法就是第⼀个参数是class,⽽静态⽅法不需要额外的参数,所以必须区分。
10、isinstance 和 type 的作⽤?
type和isinstance都可以判断变量是否属于某个内建类型
type只接收⼀个参数,不但可以判断变量是否属于某个类型,⽽且可以得到参数变量未知的所属的类型;
isinstance只能判断是否属于某个已知类型,不能直接得到变量未知的所属的类型
11、有⽤过with statement(语句)吗?它的好处是什么?
with语句会在嵌套的代码执⾏之后,⾃动关闭⽂件。这种做法的还有另⼀个优势就是,⽆论嵌套的代码是以何种⽅式结束的,它都关闭⽂件。如果在嵌套的代码中发⽣异常,它能够在外部exception handler catch异常前关闭⽂件。如果嵌套代码有return/continue/break 语句,它同样能够关闭⽂件。
12、下列数据结构中,哪⼀种是不可迭代的
'''
A. dict
B. object
C. set
D. str
'''
# 答案:
B
13、实现⼀个Singleton单例类,要求遵循基本语⾔编程规范(⽤尽量多的⽅式)。
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
java调用python模型14、请⼝述with的⽤法,如果⾃⼰的类需要⽀持with语句,应该如何书写? 基本格式
with context_expression [as target(s)]:
with-body
这⾥ context_expression 要返回⼀个上下⽂管理器对象,该对象并不赋值给 as ⼦句中的 target(s) ,如果指定了 as ⼦句的话,会将上下⽂管理器的__enter__()⽅法的返回值赋值给 target(s)。 target(s) 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。
⾃定义的上下⽂管理器要实现上下⽂管理协议所需要的 __enter__()和 __exit__()两个⽅法 context_manager.__enter__():进⼊上下⽂管理器的运⾏时上下⽂,在语句体执⾏前调⽤。with 语句将该⽅法的返回值赋值给 as ⼦句中的 target,如果指定了 as ⼦句的话
context_manager.__exit__(exc_type, exc_value, exc_traceback):退出与上下⽂管理器相关的运⾏时上下⽂,返回⼀个布尔值表⽰是否对发⽣的异常进⾏处理。
15、python 中如何判断⼀个对象是否可调⽤? 哪些对象可以是可调⽤对象?如何定义⼀个类,使其对象本⾝就是可调⽤对象?
# 答案:
# python 中如何判断⼀个对象是否可调⽤
def func():
pass
print(callable(func))# True
# 哪些对象可以是可调⽤对象
1.类对象
2.所有带有_call_()⽅法的对象
# 如何定义⼀个类,使其对象本⾝就是可调⽤对象
⼀个类实例也可以变成⼀个可调⽤对象,只需要实现⼀个特殊⽅法call()。
16、请实现⼀个栈。
class Stack(object):
def__init__(self,size):
#类的构造函数
self.size = size
self.stack =[]
def__str__(self):
#类的字符串输出⽅法,类似于java的.toString()⽅法
return str(self.stack)
def getSize(self):
#获取栈当前⼤⼩
return len(self.stack)
def push(self, x):
#⼊栈,栈满抛异常
if self.isfull():
#return -1
raise Exception("Stack is full")
self.stack.append(x)
def pop(self):
#出栈,栈空抛异常
if self.isempty():
#return -1
raise Exception("Stack is empty")
topElement = self.stack[-1]
ve(topElement)
return topElement
def isempty(self):
#判断栈空
if len(self.stack)==0:
return True
return False
def isfull(self):
#判断栈满
if len(self.stack)== self.size :
return True
return False
17、关于Python类的继承不正确的说法是?(多选)
A. Python类⽆法继承
B.可以继承,⽆法执⾏⽗类的构造函数
C.可以有多个⽗类
D.只能有⼀个⽗类
# 答案
'''
A
B
D
'''
18、实现⼀个hashtable类,对外暴露的有add和get⽅法,满⾜以下测试代码
import uuid
names ={"name","web","python"}
ht = HashTable()
for key in names:
value = uuid.uuid4()
ht.add(key, value)
print("add 元素", key, value)
for key in names:
v = ht.get(key)
print("get 元素", key, v)
# 答案:
class HashMap(object):
def__init__(self):
# 初始化总表为,容量为2的表格(含两个⼦表)
self.maps = BetterMap(2)
self.num =0# 表中数据个数
def get(self,k):
return (k)
def add(self, k, v):
# 若当前元素数量达到临界值(⼦表总数)时,进⾏重排操作# 对总表进⾏扩张,增加⼦表的个数为当前元素个数的两倍!
if self.num ==len(self.maps.maps):
# 往重排过后的 self.map 添加新的元素
self.maps.add(k, v)
self.num +=1
def resize(self):
""" 重排操作,添加新表, 注意重排需要线性的时间 """
# 先建⽴⼀个新的表,⼦表数 = 2 * 元素个数
new_maps = BetterMap(self.num *2)
for m in self.maps.maps:# 检索每个旧的⼦表
for k,v in m.items:# 将⼦表的元素复制到新⼦表
new_maps.add(k, v)
self.maps = new_maps # 令当前的表为新表
19、请⽤两个队列来实现⼀个栈(给出伪代码即可)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论