公众号上看到的python面试题10坑

问题1:请问如何修改以下Python代码,使下面的代码调用类A的show方法?

class A(object):
    def show(self):
        print('base show')

class B(A):
    def show(self):
        print('derived show')

obj = B()
obj.show()

答:题目问的是调用类A的show方法,不单单只是显示A中的show的内容,所以要通过class方法指定到A的类对象即可:

obj.__class__ = A
obj.show()

问题2:请问如何修改以下Python代码,使得代码能够运行?

class A(object):
    def __init__(self, a, b):
        self.__a = a
        self.__b = b
    def myprint(self):
        print('a=', self.__a, 'b=', self.__b)

a1 = A(10, 20)
a1.myprint()

a1(80)

答:该程序运行报了一个错误

Traceback (most recent call last):
('a=', 10, 'b=', 20)
  File "C:/Users/Lee/PycharmProjects/print/exeses.py", line 11, in <module>
    a1(80)
TypeError: 'A' object is not callable

这个错误的大致意思是将A类当成了一个方法来进行调用是不可行的。为了让对象实例能被直接调用,需要实现call方法。

#-*- coding:utf-8 -*-
class A(object):
    def __init__(self, a, b):
        self.__a = a
        self.__b = b
    def myprint(self):
        print('a=', self.__a, 'b=', self.__b)
    def __call__(self, num):#num传入
        print('call:', num + self.__a)#随意让num做一些事

a1 = A(10, 20)
a1.myprint()

a1(80)

结果

('a=', 10, 'b=', 20)
('call:', 90)

问题3:下面这段代码的输出是什么?

class B(object):
    def fn(self):
        print('B fn')
    def __init__(self):
        print('B INIT')
        
class A(object):
    def fn(self):
        print('A fn')

    def __new__(cls, a):
        print('NEW', a)
        if a > 10:
            return super(A, cls).__new__(cls)
        return B()

    def __init__(self, a):
        print('INIT', a)

a1 = A(5)
a1.fn()
a2 = A(20)
a2.fn()
答:该题的关键点在于__new__方法。 __init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 a1 = A(5) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法。所以很自然的,第一行输出为NEW 5.接着判断a是否大于10,此时a = 5,所以执行return B(),进入B类中运行;所以第二行和第三行是B类实例的调用B INIT, B fn。随后新建一个a2的类实例,将a = 20传入A类,先执行__new__,所以第四行是NEW 20,此时a大于了10,执行
return super(A, cls).__new__(cls)

大致的意思是得到当前类的实例(如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类 的__new__()方法)

所以还是实例还是在A中,第五行输出INIT 20,接着调用A类中的fn方法,输出A fn。最终结果

('NEW', 5)
B INIT
B fn
('NEW', 20)
('INIT', 20)
A fn

问题4:下面这段代码输出什么?

ls = [1, 2, 3, 4]
list1 = [i for i in ls if i > 2]
print(list1)

list2 = [i * 2 for i in ls if i > 2]
print(list2)

dic1 = {x: x ** 2 for x in (2, 4, 6)}
print(dic1)

set1 = {x for x in 'hello world' if x not in 'low level'}
print(set1)

答:该题考查列表解析和字典还有集合的生成方法。输出如下:

[3, 4]
[6, 8]
{2: 4, 4: 16, 6: 36}
set(['h', 'r', 'd'])

问题5:下面这段代码输出什么?

num = 9

def f1():
    num = 20

def f2():
    print(num)

f2()
f1()
f2()

答:该题考查全局变量和局部变量的知识。先定义一个num = 9的全局变量,接着在f1中定义了num = 20.由于局部变量只能在当前定义的函数或者类中被调用,而全局变量可以在任何函数或者类中被调用,前提是没有被同名的局部变量所覆盖。所以该题的答案很明显了,调用f2,print num 应该是全局变量的num = 9,f1中的num  f2函数无法调用;接着调用f1,没有print,所以无输出;最后再一次调用f2,f1中的num = 20 并不能直接改变全局变量的值,所以输出9.要想在局部变量中修改全局变量的值,需要使用global

num = 9

def f1():
    global num
    num = 20

def f2():
    print(num)

f2()
f1()
f2()

这样num就被修改为了20

9
20

问题6:如何使用一行代码交换两个变量的值?

a = 8
b = 9

答:

(a, b) = (b, a)

问题7:如何添加代码,使得没有定义的方法都调用mydefault方法?

class A(object):
    def __init__(self, a, b):
        self.a1 = a
        self.b1 = b
        print('init')
        
    def mydefault(self):
        print('default')
        
a1 = A(10, 20)
a1.fn1()
a1.fn2()
a1.fn3()
答:可以使用__getattr__方法解决这个问题, __getattr__函数的作用: 如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, 如果没有定义这个函数,那么抛出AttributeError异常。由此可见,__getattr__一定是作用于属性查找的最后一步,兜底。
class A(object):
    def __init__(self, a, b):
        self.a1 = a
        self.b1 = b
        print('init')

    def mydefault(self, *args):
        print('default')
    
    def __getattr__(self, item):
        return self.mydefault()#指向mydefault方法
        

a1 = A(10, 20)
a1.fn1()
a1.fn2()
a1.fn3()
这样就就不会触发异常了。还可以给mydefault方法增加一个*args不定参数来兼容。

问题8:一个包里有三个模块,mod1,py, mod2.py, mod3.py, 但使用from demopack import * 导入模块时,如何保证只有mod1, mod3被导入了?

答:在包中init.py文件,并在文件中增加:

__all__ = ['mod1', 'mod3']

python模块中的__all__w属性,可用于模块导入时限制,此时被导入模块若定义了__all__属性,则只有__all__内指定的属性、方法、类可被导入。

若没定义,则导入模块内的所有公有属性,方法和类 。

问题9:写一个函数,接收整数参数n,返回一个函数,函数返回n和参数的积。

def f1(n):
    def f2(x):
        return n * x
    return f2

num = f1(3)
print(num(9))

问题10:请问下面的代码有什么隐患?

def strtest1(num):
    str = 'first'
    for i in range(num):
        str += 'x'
    return str
答:由于变量str是个不可变对象,每次迭代,Python都会生成新的str对象来存储新的字符串,num越大,创建的str对象越多,内存消耗越大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值