python面试——操作类

Python 交换两个变量的值

在 Python 中交换两个对象的值通过下面的方式即可

a , b = b ,a 

但是需要强调的是这并不是元组解包,通过 dis 模块可以发现,这是交换操作的字节码是 ROT_TWO,意思是在栈的顶端做两个值的互换操作。

在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的作用

read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。如果希望一行一行的输出那么就可以使用 readline(),该方法会把文件的内容加载到内存,所以对于对于大文件的读取操作来说非常的消耗内存资源,此时就可以通过 readlines 方法,将文件的句柄生成一个生产器,然后去读就可以了。

json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?

可以处理的数据类型是 str、int、list、tuple、dict、bool、None, 因为 datetime 类不支持 json 序列化,所以我们对它进行拓展。

# 自定义时间序列化
import json
from datetime import datetime, date
# JSONEncoder 不知道怎么去把这个数据转换成 json 字符串的时候
# ,它就会去调 default()函数,所以都是重写这个函数来处理它本身不支持的数据类型,
# default()函数默#认是直接抛异常的。
class DateToJson(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, obj)


d = {'name': 'cxa', 'data': datetime.now()}
print(json.dumps(d, cls=DateToJson))

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

可以通过 json.dumps 的 ensure_ascii 参数解决,代码示例如下:

import json
a=json.dumps({"name":"张三"},ensure_ascii=False)
print(a)

有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中。

with open("A.txt") as f1:
    f1_txt = f1.readline()
with open("B.txt") as f2:
    f2_txt = f2.readline()
f3_txt = f1_txt + f2_txt

f3_list = sorted(f3_txt)

with open("C.txt", "a+") as f:
     f.write("".join(f3_list))

如果当前的日期为 20190530,要求写一个函数输出 N 天后的日期,(比如 N 为 2,则输出 20190601)。

这个题目考察的是 datetime 里的 timedelta 方法的使用,参数可选、默认值都为 0:datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) 通过这个参数可以指定不同的日期类型进行加减操作,这里我们需要改的是 days,代码如下:

import datetime
def datetime_operate(n: int):
    now = datetime.datetime.now()  # 获取当前时间
    _new_date = now + datetime.timedelta(days=n)  # 获取指定天数后的新日期
    new_date = _new_date.strftime("%Y%m%d")  # 转换为指定的输出格式
    return new_date
if __name__ == '__main__':
print(datetime_operate(4))

写一个函数,接收整数参数 n,返回一个函数,函数的功能是把函数的参数和 n 相乘并把结果返回。

这个题目考查了闭包的使用代码示例如下,返回函数之类型是函数对象。

def mul_operate(num):
    def g(val):
        return num * val

    return g
m = mul_operate(8)
print(m(5))

下面代码会存在什么问题,如何改进?

def strappend(num):
    str='first'
    for i in range(num):
        str+=str(i)
    return str

首先不应该使用 Python 的内置类似 str 作为变量名这里我把它改为了 s,另外在Python,str 是个不可变对象,每次迭代都会生成新的存储空间,num 越大,创建的 str 对象就会越多,内存消耗越大。使用 yield 改成生成器即可, 还有一点就是命名规范的位置,函数名改为_分割比较好,完整的代码如下:

def str_append(num):
    s = 'first'
    for i in range(num):
        s += str(i)
        yield s

if __name__ == '__main__':
    for i in str_append(3):
        print(i)

一行代码输出 1-100 之间的所有偶数。

可以通过列表生成式,然后使用与操作如果如 1 与之后结果为 0 则表明为偶数,等于 1 则为奇数。`

# 方法1
print([i for i in range(1, 101) if i & 0x1 == 0])
# 方法2:测试发现方法二效率更高
print(list(range(2, 101, 2)))

with 语句的作用,写一段代码?

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

Python 字典和 json 字符串相互转化方法

在 Python 中使用 dumps 方法 将 dict 对象转为 Json 对象,使用 loads 方法可以将 Json 对象转为 dict 对象。

dic = {'a': 123, 'b': "456", 'c': "liming"}
json_str = json.dumps(dic)
dic2 = json.loads(json_str)
print(dic2)
打印:
'{"a": 123, "b": "456", "c": "liming"}'
{'a': 123, 'b': '456', 'c': 'liming'}

我们再来看一个特殊的例子

import json
dic = {'a': 123, 'b': "456", 'c': "liming"}
dic_str = json.loads(str(dic).replace("'", "\""))
print(dic_str)

下面我解释下上面代码是测试什么:
首先 json.loads(jsonstr) 这里面的参数只能是 jsonstr 格式的字符串.
当我们使用 str 将字典 dic 转化为字符串以后,得到的结果为:"{‘a’: 123, ‘b’: ‘456’, ‘c’: ‘liming’}"。
如果直接使用 json.loads(str(dic)) 你会发现出现错误,原因就是,单引号的字符串不符合Json的标准格式所以再次使用了 replace("’", “”")。得到字典
其实这个例子主要目的是告诉大家 Json 的标准格式是不支持单引号型字符串的,否则会出现以下错误。
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

请写一个 Python 逻辑,计算一个文件中的大写字母数量

with open('A.txt') as fs:
    count = 0
    for i in fs.read():
        if i.isupper():
            count += 1
print(count)

请写一段 Python连接Mongo数据库,然后的查询代码。

import pymongo
db_configs = {
    'type': 'mongo',
    'host': '地址',
    'port': '端口',
    'user': 'spider_data',
    'passwd': '密码',
    'db_name': 'spider_data'
}


class Mongo():
    def __init__(self, db=db_configs["db_name"], username=db_configs["user"],
                 password=db_configs["passwd"]):
        self.client = pymongo.MongoClient(f'mongodb://{db_configs["host"]}:db_configs["port"]')
        self.username = username
        self.password = password
        if self.username and self.password:
            self.db1 = self.client[db].authenticate(self.username, self.password)
        self.db1 = self.client[db]
 def find_data(self):
        # 获取状态为0的数据
        data = self.db1.test.find({"status": 0})
        gen = (item for item in data)
        return gen

if __name__ == '__main__':
    m = Mongo()
print(m.find_data())

说一说Redis的基本类型

答: Redis 支持五种数据类型: string(字符串) 、 hash(哈希)、list(列表) 、 set(集合) 及 zset(sorted set: 有序集合)。

请写一段 Python连接Redis数据库的代码。

from redis import StrictRedis, ConnectionPool
redis_url="redis://:xxxx@112.27.10.168:6379/15"
pool = ConnectionPool.from_url(redis_url, decode_responses=True)
r= StrictRedis(connection_pool=pool)

请写一段 Python连接Mysql数据库的代码。

conn = pymysql.connect(host='localhost', 
port=3306, user='root', 
passwd='1234', db='user', charset='utf8mb4')#声明mysql连接对象
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)#查询结果以字典的形式
cursor.execute(sql语句字符串)#执行sql语句
conn.close()#关闭链接

了解Redis的事务么

简单理解,可以认为 redis 事务是一些列 redis 命令的集合,并且有如下两个特点: 1.事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 2.事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。 一般来说,事务有四个性质称为ACID,分别是原子性,一致性,隔离性和持久性。 一个事务从开始到执行会经历以下三个阶段:
• 开始事务
• 命令入队
• 执行事务 代码示例:

import redis
import sys
def run():   
    try:
        conn=redis.StrictRedis('192.168.80.41')
       # Python中redis事务是通过pipeline的封装实现的
        pipe=conn.pipeline()
        pipe.sadd('s001','a')
        sys.exit()
        #在事务还没有提交前退出,所以事务不会被执行。
        pipe.sadd('s001','b')
        pipe.execute()
        pass
    except Exception as err:
        print(err)
        pass
if __name__=="__main__":
      run()

了解数据库的三范式么?

经过研究和对使用中问题的总结,对于设计数据库提出了一些规范,这些规范被称为范式 一般需要遵守下面3范式即可: 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。 第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。 第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。

了解分布式锁么

分布式锁是控制分布式系统之间的同步访问共享资源的一种方式。 对于分布式锁的目标,我们必须首先明确三点:
• 任何一个时间点必须只能够有一个客户端拥有锁。
• 不能够有死锁,也就是最终客户端都能够获得锁,尽管可能会经历失败。
• 错误容忍性要好,只要有大部分的Redis实例存活,客户端就应该能够获得锁。 分布式锁的条件 互斥性:分布式锁需要保证在不同节点的不同线程的互斥 可重入性:同一个节点上的同一个线程如果获取了锁之后,能够再次获取这个锁。 锁超时:支持超时释放锁,防止死锁 高效,高可用:加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。 支持阻塞和非阻塞:可以实现超时获取失败,tryLock(long timeOut) 支持公平锁和非公平锁
分布式锁的实现方案 1、数据库实现(乐观锁) 2、基于zookeeper的实现 3、基于Redis的实现(推荐)

用 Python 实现一个 Reids 的分布式锁的功能

REDIS分布式锁实现的方式:SETNX + GETSET,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists。 多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。 如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。

import time
import redis
from conf.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD

class RedisLock:
    def __init__(self):
        self.conn = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=1)
        self._lock = 0
        self.lock_key = ""
    @staticmethod
    def my_float(timestamp):
        """
        Args:
            timestamp:
        Returns:
            float或者0
            如果取出的是None,说明原本锁并没人用,getset已经写入,返回0,可以继续操作。
        """
        if timestamp:
            return float(timestamp)
        else:
            #防止取出的值为None,转换float报错
            return 0
 @staticmethod
    def get_lock(cls, key, timeout=10):
        cls.lock_key = f"{key}_dynamic_lock"
        while cls._lock != 1:
            timestamp = time.time() + timeout + 1
            cls._lock = cls.conn.setnx(cls.lock_key, timestamp)
            # if 条件中,可能在运行到or之后被释放,也可能在and之后被释放
            # 将导致 get到一个None,float失败。
            if cls._lock == 1 or (
                            time.time() > cls.my_float(cls.conn.get(cls.lock_key)) and
                            time.time() > cls.my_float(cls.conn.getset(cls.lock_key, timestamp))):
                break
            else:
                time.sleep(0.3)
  @staticmethod
    def release(cls):
        if cls.conn.get(cls.lock_key) and time.time() < cls.conn.get(cls.lock_key):
            cls.conn.delete(cls.lock_key)


def redis_lock_deco(cls):
    def _deco(func):
        def __deco(*args, **kwargs):
            cls.get_lock(cls, args[1])
            try:
                return func(*args, **kwargs)
            finally:
                cls.release(cls)
        return __deco
    return _deco


@redis_lock_deco(RedisLock())
def my_func():
    print("myfunc() called.")
    time.sleep(20)

if __name__ == "__main__":
my_func()

写一段 Python 使用 mongo 数据库创建索引的代码:

import pymongo
db_configs = {
    'type': 'mongo',
    'host': '地址',
    'port': '端口',
    'user': 'spider_data',
    'passwd': '密码',
    'db_name': 'spider_data'
}


class Mongo():
    def __init__(self, db=db_configs["db_name"], username=db_configs["user"],
                 password=db_configs["passwd"]):
        self.client = pymongo.MongoClient(f'mongodb://{db_configs["host"]}:{db_configs["port"]}')
        self.username = username
        self.password = password
        if self.username and self.password:
            self.db1 = self.client[db].authenticate(self.username, self.password)
        self.db1 = self.client[db]

    def add_index(self):
        """
          通过create_index添加索引
        """
        self.db1.test.create_index([('name', pymongo.ASCENDING)], unique=True)

    def get_index(self,):
        """
          查看索引列表
        """
        indexlist=self.db1.test.list_indexes()
        for index in indexlist:
            print(index)

if __name__ == '__main__':
    m = Mongo()
    m.add_index()
    print(m.get_index())

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值