Python企业面试题3 —— 基础篇

1. py面向对象中的继承有什么特点?

继承概念的实现方式主要有2类:实现继承、接口继承。
实现继承是指使用基类的属性和方法而无需额外编码的能力;
接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法):
python两种类:经典类 新式类
py3新式类 —— 都默认继承 object class Animal(object): == class Animal:
py2经典类和新式类 并存
class Animal:经典类 —— 继承顺序 个别使用方法
class Animal(object): 新式类
继承分为单继承和多继承
Python是支持多继承的
如果没有指定基类,py的类会默认继承object类,object是所有py类的基类,它提供了一些常见的方法(如__str__)的实现。

对象可以调用自己本类和父类的所有方法和属性,先调用自己的,自己没有才调用父类的。谁(对象)调用方法,方法中的self就指向谁

class Foo:
    def __init__(self):
        self.func()

    def func(self):
        print('Foo.func')

class Son(Foo):
    def func(self):
        print('Son.func')

s = Son()
s.func()

# -=======================================================

class A:
    def get(self):
        self.say()
    def say(self):
        print('AAAAA')
class B(A):
    def say(self):
        print('BBBBB')

b = B()
b.get()     # BBBBB
2. 面向对象中 super 的作用?
# 用于子类继承基类的方法
class FooParent(object):
    def __init__(self):
        self.parent = 'I\'m the parent.'
        print('Parent')
        print('1111')

    def bar(self, message):
        print("%s from Parent" % message)


class FooClild(FooParent):
    def __init__(self):
        # super(FooChild, self)首先找到FooChild 的父类(就是类FooParent),然后把类B的对象,
        # FooChild转换为类FooParent的对象
        super(FooClild, self).__init__()
        print('Child')

    def bar(self, message):
        super(FooClild, self).bar(message)
        print('Child bar function')
        print(self.parent)

if __name__ == '__main__':
    foochild = FooClild()
    foochild.bar('HelloWorld')
3. 列举面向对象中带双下划线的特殊方法,如:__new____init__

__new__:生成实例
__init__:生成实例的属性
__call__:实例对象加( )会执行def __call__:...... 方法里面的内容
__del__:析构方法,当对象在内存中被释放时,自动触发执行。如当del obj或者应用程序运行完毕时,执行该方法里面的内容
__enter____exit__:出现with语句,对象的__enter__被处罚,有返回值则赋值给as声明的变量;with中代码块执行完毕时执行 __exit__里面的内容。
__module__:表示当前操作的对象在哪个模块 obj.__module__
__class__:表示当前操作的对象类型是什么 obj.__class__
__doc__类的描述信息的是,显示print信息无法判断
__str__:对边对象的字符串显示,显示print函数 obj.__str__()
__repr__:改变对象的字符串显示,交互式解析器 obj.__repr__()
__format__:自定义格式化字符串
__slots__:一个类变量,用来限制实例可以添加的属性的数量和类型
__setitem____getitem____delitem__

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

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1 = Foo('sb')
f1['age'] = 18
f1['age1'] = 19
del f1.age1
del f1['age']
f1['name'] = 'alex'
print(f1.__dict__)

__get__():调用一个属性时触发
__set__():为一个属性赋值时触发
__delete__():采用del删除属性时触发

4. 如何判断是函数还是方法?
看他的调用者是谁,如果是类,就需要传入一个参数self的值,这时他就是一个函数。如果调用者是对象,就不需要给self传入参数值,这时他就是一个方法。
5. 静态方法和类方法的区别?

尽管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明显的区别。classmethod 必须有一个指向类对象的引用作为第一个参数,而staticmethod 可以没有任何参数。

# 举个例子:
class Num:
    # 普通方法:能够用Num调用而不能用实例化对象调用
    def one():
        print('1')
    # 实例方法:能用实例化对象调用而不能用Num调用
    def two(self):
        print('2')
    # 静态方法:能够用Num和实例化对象的调用
    @staticmethod
    def three():
        print('3')
    # 类方法:第一个参数cls长什么样不重要,都是指Num类本身,调用时将Num类作为对象隐式的传入方法
    @classmethod
    def go(cls):
        cls.three()

Num.one()   # 1
# Num.two()   # 报错
Num.three()     # 3
Num.go()    # 3

i = Num()
# i.one() # TypeError: one() takes 0 positional arguments but 1 was given
i.two()     # 2
i.three()   # 3
i.go()      # 3
6. 什么是反射?以及应用场景?

反射的核心本质就是以字符串的形式去导入个模块,利用字符串的形式去执行函数。
Django中的CBV就是基于反射实现的。

7. 装饰器的写法以及应用场景?

含义:装饰器本质就是函数,为其他函数添加附加功能
原则:

  • 不修改被修饰函数的代码
  • 不修改被修饰函数的调用方式
    应用场景:
  • 无参装饰器在用户登录、认证中常见
  • 有参装饰器在flask的路由系统中见到过
import functools

def wrapper(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        print('我是装饰器')
        return func
    return inner

@wrapper
def index():
    print('我是被装饰函数')
    return None

index()

# 应用场景
- 高阶函数
- 闭包
- functools.wraps(func)
8. 异常处理写法以及如何主动抛出异常(应用场景)
# 触发异常
def temp_convert(var):
    try:
        return int(var)
    except ValueError as Argument:
        print("参数没有包含数字%s" % Argument)

# 调用函数
temp_convert("xyz")
# 以10为基数的int()的无效文字:“xyz”

# raise 语法
class Networkerror(RuntimeError):
    def __init__(self, arg):
        self.args = arg

try:
    raise Networkerror("Bad hostname")
except Networkerror as e:
    print(e.args)
9. 什么是面向对象的mro?

mro就是方法解析顺序

10. isinstance作用以及应用场景?

isinstance(对象、类) 判断这个对象是不是这个类或者这个类的子类的实例化

# 判断a属不属于A这个类(可以判断到祖宗类)
class A:
    pass

class B:
    pass

a = A()
b = B()
print(isinstance(b, A))     # True 判断到祖宗类

# 任何与object都是True,内部都继承object
print(isinstance(a, object))    # True

应用场景:
rest framework 认证的流程
scrapy-redis

11. json序列化时,默认遇到中文会转换成Unicode,如果想要保留中文怎么办?

在序列化时,中文汉字总是被转换为Unicode码,在dumps函数中添加参数ensure_ascii=False即可解决。

12. 简述yield和yield from关键字?

yield和yield from是Python中用于生成器函数的关键字。
(1) yield关键字:

  • yield用于定义一个生成器函数,生成器函数可以通过yield语句来产生一个值,并且暂停函数的执行状态,保存当前的上下文环境。
  • 当生成器函数被调用时,它会返回一个生成器对象,而不是立即执行函数体内的代码。
  • 每次调用生成器对象的__next__()方法或者使用for循环迭代时,生成器函数会从上次暂停的位置继续执行,直到遇到下一个yield语句。

(2) yield from关键字:

  • yield from用于在生成器函数内部委托另一个可迭代对象(包括生成器)来产生值。
  • 它可以简化生成器函数内部的迭代过程,将迭代的责任交给被委托的可迭代对象。
  • 当使用yield from委托一个可迭代对象时,生成器函数会自动处理子生成器的暂停和恢复。
posted @ 2024-04-13 14:34  生而自由爱而无畏  阅读(22)  评论(0编辑  收藏  举报