编辑
2024-04-06
面试题
00
请注意,本文编写于 442 天前,最后修改于 442 天前,其中某些信息可能已经过时。

目录

1、python实现单例模式
2、反转一个整数,如-123,-321
3、设计实现遍历目录与子目录,抓取.pyc文件

基础部分:企业真题

1、python实现单例模式

python
# -*- coding: utf-8 -*-# # ------------------------------------------------------------------------------- # Name: 14、python实现单例模式 # Description: 单例模式是一个软件的设计模式,为了保证一个类,无论调用多少次产生的实例对象, # 都是指向同一个内存地址,仅仅只有一个实例(只有一个对象)。实现单例模式的手段有很多种,但总的 # 原则是保证一个类只要实例化一个对象,下一次再实例的时候就直接返回这个对象,不再做实例化的操作。 # 所以这里面的关键一点就是,如何判断这个类是否实例化过一个对象。 # Author: zhaoyaowei # Date: 2023/3/29 23:43 # ------------------------------------------------------------------------------- # 方法一:通过模块导入 """ 基本原理:借用了模块导入时的底层原理实现。 当一个模块(py文件)被导入时,首先会执行这个模块的代码,然后将这个模块的名称空间加载到内存。 当这个模块第二次再被导入时,不会再执行该文件,而是直接在内存中找。 于是,如果第一次导入模块,执行文件源代码时实例化了一个类,那再次导入的时候,就不会再实例化。 """ import threading # 方法二:通过类绑定方法 class Student: """ @classmethod修饰符对应的函数不需要实例化, 不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数, 可以来调用类的属性,类的方法,实例化对象等 原理:类的绑定方法是第二种实例化对象的方式, 第一次实例化的对象保存成类的数据属性 _instance, 第二次再实例化时,在get_singleton中判断已经有了实例对象, 直接返回类的数据属性 _instance """ _instance = None # 记录实例化对象, 属性默认为类属性,可直接被类本身调用 def __init__(self, name, age): # self: 表示实例化的地址id self.name = name self.age = age # 类方法(不需要实例化类就可以被类本身调用) @classmethod def get_singleton(cls, *args, **kwargs): # cls:表示没用被实例化的类本身 if not cls._instance: cls._instance = cls(*args, **kwargs) return cls._instance # 补充:该方式实现的单例模式有一个明显的bug;原因在于若不通过绑定类的方法实例化对象,而是直接通过类名加括号实例化对象,就不是单例模式了 s1 = Student.get_singleton("tom", 2) s2 = Student.get_singleton("tom", 2) print(s1, s2, s1 is s2) # <__main__.Student object at 0x102f80fa0> <__main__.Student object at 0x102f80fa0> True print(s1.__dict__, s2.__dict__) # {'name': 'tom', 'age': 2} # 方法三:通过__new__ class Student: """ 原理:和方法2类似,将判断的实现方式,从类的绑定方法中转移到类的__new__中 思路都是判断类有没有实例,有则直接返回,无则实例化并保存到_instance中。 __new__ 方法:使用 类名()创建对象时,Python解释器首先会调用object基类提供__new__方法为对象分配空间 作用有两个:(1)在内存中为对象分配空间 (2)返回对象的引用 若获取到对象的引用后,将引用作为第一个参数,传递给__init__方法;否则不会调用init __init__ 方法:(1)对象初始化 (2)定义实例属性 """ _instance = None def __init__(self, name, age): self.name = name self.age = age def __new__(cls, *args, **kwargs): # if cls._instance: # return cls._instance # 有实例,直接返回 # else: # cls._instance = super().__new__(cls) # 没有实例,则new一个实例并保存 # return cls._instance # 返回给init,再实例化一次 if not cls._instance: # 简写 cls._instance = super().__new__(cls) return cls._instance # 补充:这种方式可以近乎完美地实现单例模式,但是依然不够完美。不完美的地方在于没有考虑到并发的极端情况下,有可能多个线程同一时刻实例化对象。 s1 = Student("tom", 3) s2 = Student("tom", 3) print(s1, s2, s1 is s2) # <__main__.Student object at 0x102de9c40> <__main__.Student object at 0x102de9c40> True print(s1.__dict__, s2.__dict__) # {'name': 'tom', 'age': 3} # 方法三优化版: class Student: _instance = None _lock = threading.RLock() # 加互斥锁方法 def __new__(cls, *args, **kwargs): if cls._instance: # 如果已经有单例,则不再抢锁,避免IO等待 return cls._instance # 只有第一个抢到锁的线程实例化一个对象,并保存在_instance中, # 同一时刻抢锁的其他线程再抢到锁后,不会进入判断if not cls._instance, # 直接返回保存在_instance的对象 with cls._lock: # 使用with语法,方便抢锁和释放锁 if not cls._instance: cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance # 方法四:函数装饰器 def singleton(cls): _instance = {} # 采用字典,可以装饰多个类实现单例模式 def inner(*args, **kwargs): if cls not in _instance: _instance[cls] = cls(*args, **kwargs) return _instance.get(cls) return inner # 逻辑:实例化对象时,将类对象作为参数传值给singleton(),再将函数执行完成的返回值反馈回类 @singleton class Student: def __init__(self, name, age): self.name = name self.age = age # def __new__(cls, *args, **kwargs): # 将方法3中的重写new搬到了函数装饰器中 # if not cls._instance: # cls._instance = super().__new__(cls) # return cls._instance s1 = Student("tom", 4) s2 = Student("tom", 4) print(s1, s2, s1 is s2) # <__main__.Student object at 0x103119670> <__main__.Student object at 0x103119670> True print(s1.__dict__, s2.__dict__) # {'name': 'tom', 'age': 4} # 方法五:类装饰器 class Singleton: """ 原理:在函数装饰器的思路上,将装饰器封装成类。 程序会实例化一个Student对象,这个对象是SingleTon的对象。 后面使用的Student本质上使用的是SingleTon的对象。 所以使用Student('tom', 5)来实例化对象,其实是在调用SingleTon的对象,会触发其__call__的执行 所以就在__call__中,判断Student类有没有实例对象了。 """ _instance = {} def __init__(self, cls_name): self.name = cls_name # 若类定义类__call__方法,则将一个类的实例化对象变成了可调用对象 # Student('tom', 5) == Student.__call__('tom', 5) def __call__(self, *args, **kwargs): if self.name not in Singleton._instance: Singleton._instance[self.name] = self.name(*args, **kwargs) return self._instance.get(self.name) @Singleton # 相当于Student = SingleTon(Student),即Student是SingleTon的实例对象 class Student: def __init__(self, name, age): self.name = name self.age = age s1 = Student("tom", 5) s2 = Student("tom", 5) print(s1, s2, s1 is s2) # <__main__.Student object at 0x100915550> <__main__.Student object at 0x100915550> True print(s1.__dict__, s2.__dict__) # {'name': 'tom', 'age': 5} {'name': 'tom', 'age': 5}

2、反转一个整数,如-123,-321

python
# -*- coding: utf-8 -*-# # ------------------------------------------------------------------------------- # Name: 反转一个整数,如-123,-321 # Description: # Author: zhaoyaowei # Date: 2023/4/1 20:51 # ------------------------------------------------------------------------------- def reverse_integer1(x): if x >= 0: # 如果是正数,直接反转 rev_x = int(str(x)[::-1]) else: # 如果是负数,先反转绝对值,再加上负号 rev_x = -int(str(abs(x))[::-1]) return rev_x def reverse_integer2(x): sign = 1 if x >= 0 else -1 x = abs(x) rev_x = int(str(x)[::-1]) return sign * rev_x print(reverse_integer2(123)) # 输出:321 print(reverse_integer2(-123)) # 输出:-321 print(reverse_integer2(120)) # 输出:21

3、设计实现遍历目录与子目录,抓取.pyc文件

python
# -*- coding: utf-8 -*-# # ------------------------------------------------------------------------------- # Name: 设计实现遍历目录与子目录,抓取.pyc文件 # Description: # Author: zhaoyaowei # Date: 2023/4/1 21:18 # ------------------------------------------------------------------------------- import os import fnmatch def find_pyc_files(dir_path): pyc_files = [] for root, dirs, files in os.walk(dir_path): for file in files: if fnmatch.fnmatch(file, '*.pyc'): pyc_files.append(os.path.join(root, file)) return pyc_files print(os.getcwd()) pyc_files = find_pyc_files('/Users/zhaoyaowei/Desktop/project/InterviewQuestions/Python基础') print(pyc_files)
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:赵耀伟

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!