问题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对象越多,内存消耗越大。