【PythonCode】字符拼接特殊语法和函数传参调用等

【PythonCode】字符拼接特殊语法和函数传参调用等

前言

在很多高大上的项目中,一个花费很长时间、消耗大量人力物力才查出来的BUG,经常是一个符号错误、一个值传错、一个基本函数的用法没有考虑周到等基本问题,所以基础不牢、地动山摇,真的不是开玩笑。
今天继续更新【PythonCode】系列。

1. 以下程序的输出结果是:

a = [4, 5, 3, 6, 7, 8, 2, 9, 1]
m, c = 1, 1
for i in range(1, len(a)):
    if a[i] >= a[i-1]:
        c += 1
        m = max(m, c)
    else:
        c = 1
print(c, m)

A. 1 1
B. 1 4
C. 2 4
D. 3 4

这是一个Python基础的综合题目,a 是一个数字组成的列表,从索引1的数字开始遍历,如果数字大于或等于前一个,变量c就从1开始自增,并且比较变量c和变量m的值,把更大的数字赋值给m。如果a中的数字比前一个小,则c重新被赋值为1。a中的最后一个数字比倒数第二个数字小,所以最后c的值被重置为1,连续数字大于等于前一个数字的数字串为4个:3, 6, 7, 8,在遍历这段数字时c会连续自增三次,最大为4,所以m的值为4,答案为B。

2. 以下代码的执行结果是:

a = "Python等级考试"
b = '='
c = '>'
print("{0:{1}{3}{2}}".format(a, b, 25, c))

A. Python等级考试>>>>>>>>>>>>>>>
B. >>>>>>>>>>>>>>>Python等级考试
C. Python等级考试===============
D. ===============Python等级考试

此题在Python字符串拼接时用了两层大括号,还使用了冒号加尖括号的语法,所以要先理解两者的用法。

大括号是字符串拼接时用于“占位”的语法,每个大括号中拼接format()传入的内容,可以在大括号中传入format()中值的索引,如{0}。

冒号加尖括号的语法格式为:拼接值+冒号+一个字符+尖括号(左右都可以)+数字。如果拼接值的长度大于等于最后的数字,则不做处理,如果拼接值的长度小于数字,则用冒号后面的字符填充字符串使长度等于尖括号后的数字。如果尖括号为 > 则在左侧填充字符,如果尖括号为 < ,则在右侧填充。冒号和尖括号中间只能有一个字符,不能传多个,如果没有字符,会用空格填充。

题中嵌套了两层大括号,这种情况,先拼接内部的三个大括号,{1}{3}{2} 对应format()传入的后三个值:b, 25, c ,拼接结果是字符串 ‘=>25’ 。此时看外层的大括号,当前拼接的中间状态是 {‘0:=>25’},大括号中有冒号加尖括号的语法,0对应format()传入的第一个值 a,a 的长度为10,最后的数字为25,冒号后面的字符是等号 = ,尖括号为 > ,是在 a 的左侧填充,所以结果为在字符串 a 的左侧填充15个等号。答案为D。

3. 下列代码的输出是:

print("{:.0f}".format(10.5555))
print("{:.2f}".format(10.5555))
print("{:.2f}".format('10.5555'))

A.

11
10.56
10.56

B.

10
10.56
10.56

C.

10
10.56
ValueError: Unknown format code 'f' for object of type 'str'

D.

11
10.56
ValueError: Unknown format code 'f' for object of type 'str'

本题也是字符串拼接,需要拼接的是浮点数,在大括号中,语法为 冒号+点+数字+f,f 表示拼接的是浮点数,冒号后的点和数字表示小数点后保留多少位。

第一次打印,小数点后保留0位,数字10.5555被四舍五入后结果为11,第二次打印,小数点后保留两位,结果为10.56,第三次打印,format()中传入的浮点数被改成了字符串,会报错。答案为D。

4. 下面对del关键字使用错误的是:
A.

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
del my_list[1:4]

B.

class MyClass:
    a = 10
    def func(self):
        print('hello')


print(MyClass)
del MyClass

C.

class Foo:
    def __init__(self, numbers):
        self.numbers = numbers


foo = Foo([1, 2, 3])
del foo[0]

D.

person = {'name': 'Sam', 'age': 25, 'profession': 'Programmer'}
del person['profession']

del 是Python中的关键字,用于删除对象或变量等。A选项中,用del从列表中删除索引1到3(Python切片是左闭右开)的三个值,能正常删除成功。B选项中,定义了一个类然后将这个类删除,Python中一切皆对象,这里是删除一个类,能正常删除成功。C选项中,定义了一个类,并实例化了一个类对象foo,此时的foo是一个类的实例化对象,而不是一个列表,del foo[0]会报错。如果 del foo 则可以正常删除,所以答案为C。D选项中,用del删除字典中的一个键值对,能正常删除成功。

5. 以下关于索引使用正确的是:
A.

data = [1, 2, 3]
print(data[object])

B.

test_tuple = (1, 2, 3)
def function():
    return test_tuple[None]

C.

data = [1, 2, 3, 4]
o = object()
print(data[:o])

D.

data = [1, 2, 3, 4]


class A:
    def __index__(self):
        return 1


a = A()
print(data[:a])

A选项中,使用索引时用data[object],索引必须是整数(或切片),所以有语法错误(报错是报类型错误)。B选项中,test_tuple[None] 这种用法也是错误的,不存在为None的索引,语法错误。C选项中,在切片时用了一个基类的实例对象 o,切片语法中要使用数字,所以也是语法错误。D选项中,用类对象a来做切片,这里与C选项中的区别是,在A类中实现了__index__()魔法方法,用于将对象转化成整数索引。所以最后切片时返回的是数字1,可以正常切片成功,答案为D。

6. 当使用 from module import * 语句时,会导入这个包中所有非下划线开头的成员,__all__变量可以设置被导入的内容,下面写法正确的是:

A.

__all__ = ('func1',)

B.

__all__ = [func1]

C.

__all__ = ('func1')

D.

__all__ = list('func1')

_all_ 是Python中用于控制允许被导入内容的特殊变量(白名单),用于控制当前模块中可以被其他代码导入的变量、函数、类等。

在使用导包的语句(如 from module import * )时,会先检查该模块是否定义了 _all_ 变量,如果有定义,那么导入_all_ 变量中的变量、函数、类,如果没有定义,那么导入该模块中所有非下划线开头的功能。

__all__的语法为一个列表,列表中是允许被导的变量、函数、类的字符串名称,所以本题答案为D。

7. 以下关于属性访问和对象调用,错误的是:
A.

a = '1'
print(a.real)

B.

a = 1
print(a.real)

C.

class CLanguage:
    def info(self):
        print('学Python')


clang = CLanguage()
CLanguage.info(clang)

D.

a = lambda: '1'
print(a())

Python对象调用和属性访问,函数和类的调用是在函数名或类名后加括号调用,属性访问用点连接调用。参考:Python中dir,hasattr,getattr,setattr,vars的使用

A选项中,字符串没有real这个属性,会报属性错误,所以答案为A。B选项中,real属性是获取一个数的实部,结果为1。C选项中,先实例化了一个类的对象,然后直接用类名调用类方法,将实例化对象传入,代码会正常执行类方法中的功能。D选项中,a是一个匿名函数,匿名函数也可以通过 a() 的方式调用,代码可以正常执行。

8. 以下关于函数调用,将会导致运行报错的是:
A.

def foo(x, y):
    z = x +y

value = foo(10, 10)
print(value)

B.

def foo(x, y):
    return x + y

value = foo(10, 10)
print(value)

C.

def foo(x, y):
    return x + y

foo(1)

D.

def foo(x, y):
    return x + y

foo(1, 2)

本题的关键是函数调用时的传参和返回值,A选项中,foo函数将两个参数相加,但没有将结果返回,调用后执行成功,但是value的值为None。B选项中,foo函数将两个参数相加并返回,调用后执行成功,value接收了返回值,结果为20。C选项中,调用时只给函数foo传了一个参数,运行会报错,所以答案为C。D选项中,函数正常调用,只是没有用变量接收函数的返回值。

函数根据是否有参数和返回值可以分为四类:无参数无返回值,无参数有返回值,有参数无返回值,有参数有返回值。不管哪种类型,传参时要与函数的参数对应,接收返回值时要确认函数是否有返回值,无返回值时接收到的是None。

9. 以下关于函数参数传递,正确的是:
A.

def foo(key=None, value=None):
    return {key: value}

foo(k='x', v=1)

B.

def foo(x, y):
    return x + y

foo(1, x=1, y=2)

C.

def target(pos, *keyword):
    return pos + keyword


def not_forward_kwargs(*args, **kwargs):
    target(*args)

D.

def test(a, b):
    return a, b


test(1, 24)
test(1, b=24, **{})

继续巩固函数传参,A选项中,函数有两个关键字参数,将两个参数组成字典返回,参数名为key和value,函数调用时给k和v传参,不存在k和v这两个参数,代码会报错,可以改成foo(key=‘x’, value=1)。

B选项中,函数有两个位置参数,将两个参数的值相加后返回,调用时,传了三个参数,第一个实参传给x,但又用关键字的方式给x传了一次值,这就造成了多次给x传值,代码会报错。用键值对的方式给位置参数传参是支持的,错误的原因是给x传了多个值,可以改成foo(1, y=2)或foo(x=1, y=2)。

C选项中,定义了两个函数,第一个函数有一个位置参数和一个可变位置参数,第二个函数有一个可变位置参数和一个可变关键字参数,在第二个函数内调用了第一个函数,传入可变参数。这里涉及到可变参数,所以先了解可变参数的用法。

有两个重点,第一,在定义函数时,可变位置参数前是一个星号,通常的写法是*args,可变关键字参数前是两个星号,通常的写法是**kwargs。第二,在调用可变参数时,位置参数会被打包成一个元组,关键字参数会被打包成一个字典。对于位置参数,如果在函数内部直接使用元组,则语法为args,如果要解开元组使用元组中的每一个值,语法为*args。对于关键字参数,如果在函数内部直接使用字典,语法为kwargs,如果使用字典的键,语法为*kwargs,如果要使用键值对,语法为**kwargs。

回到选项,虽然第一个函数中第二个参数的英文拼写不是args,但是语法为一个星号,这是一个可变位置参数。第一个函数中的pos是必须传的,而第二个函数的参数都是可变参数,可传可不传。在定义函数时不会有问题,但在调用函数时,很可能会出现参数报错。第二个函数可以修改为:

def not_forward_kwargs(pos, *args, **kwargs):
    target(pos, *args)

D选项中,函数有两个参数,第一次调用时,传入两个参数,第二次调用时,第二个参数用关键字参数的方式传入,这种语法是支持的,后面还将一个空字典解成键值对传入,因为是空字典,解开后没有任何键值对,不影响函数执行,代码有点多余,但传参方式是正确的。

10. 以下关于函数参数传递,正确的是:
A.

def foo(a, b):
    return a + b


def do(func, *args, **kwargs):
    return func(*args, **kwargs)


do(foo, 1, 2)
do(foo, a=1, b=2)

B.

def foo(**kwargs):
    print(kwargs)


foo(**(1, 2, 3))

C.

def foo(**kwargs):
    print(kwargs)


foo(**{'name': 'kevin', 'age': 20})

D.

def foo(**kwargs):
    print(kwargs)


foo(name='kevin', age=20)

继续巩固函数传参,如果理解了上一题中说的函数传参,这题就很简单。A选项中,将一个函数传入到do()函数中调用,func和do都支持可变位置参数和可变关键字参数,所以两次执行都是正确的。B选项中,传参时在一个元组前加了两个星号,两个星号是将字典解成键值对,用在元组上有语法错误,所以答案为B。C选项解开字典后,相当于D选项,这是两种不同的写法。


相关阅读:【PythonCode】eval()函数巩固和复数模运算等

欢迎 点赞 收藏⭐ 评论 关注 如有错误敬请指正!

☟ 学Python,点击下方名片关注我。☟

你可能感兴趣的:(Python,Code/Python面试题,python,字符串拼接,函数调用,函数传参)