开发者笔记

目录

1.叠加装饰器的装饰顺序与执行顺序

装饰顺序:从下往上(被装饰函数)
执行顺序:从上往上(python代码的执行顺序)

1.1无参装饰器模板:

def outter(func):
    @wraps(func)
    def inner(*args, **kwargs):

        # 装饰前做的事
        return func(*args, **kwargs)
        # 装饰后做的事
    retur inner

给函数添加测试运行时间的功能:

import time
from functools import wraps
def outter(func):
    @wraps(func)
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(end_time-start_time)
        return res
    return inner
 
 @outter
def time_func():
    time.sleep(1)

time_func()

1.2有参装饰器

from functools import wraps

def wrappers(params1,params2,params3):
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):

            # 装饰前做的事
                return func(*args, **kwargs)
            # 装饰后做的事

        return inner
    return outter

2.什么是无参装饰器与有参装饰器

无参装饰器:被装饰的函数不需要参数,两层
有参装饰器:被装饰的函数需要参数,三层

说白了,有参装饰器就是再无参装饰器的基础上又添加了一层包装,目的:添加一个参数。那么有没有可能四层、五层?答案是没必要。因为四层、五层就意味着传递了更多的参数,那么我们用三层就能达到效果。所有装饰器最多三层

3.简述可迭代对象,迭代器对象及迭代取值方式,及for循环内部原理

3.1迭代器

迭代器:迭代取值的工具 ——(用__iter__生成迭代器对象)

优点:1.不依赖与索引取值

   2.内存中只占一份空间,不会内存溢出,节约空间,运行效率更高*(执行一次__next__取值一次,而不是一次全部取值)*

缺点:1.不能获取指定的元素

   2.只能依次往后取值

3.2 迭代协议

class MyIter:
    """num传入 用来指定迭代次数 """

    def __init__(self, num):
        self.num = num
        self.c = 0
        
    # 迭代
    def __iter__(self):
        return self
    
    # 取值
    def __next__(self):
        self.c += 1
        if self.c <= self.num:
            return "jeff"
        else:
            raise StopIteration

# 循环取值
for i in MyIter(10):
    print(i)

3.2 for 循环内部原理

1、在遍历Foo的实例对象时,执行for...in...时,首先会先执行__iter__()方法,将此对象变为迭代器。
2、__iter__方法返回了一个迭代器对象,而后调用next()方法进行循环

4.迭代器对象的优缺点是什么?

优点:1.不依赖与索引取值

   2.内存中只占一份空间,不会内存溢出,节约空间,运行效率更高*(执行一次__next__取值一次,而不是一次全部取值)*

缺点:1.不能获取指定的元素

   2.只能依次往后取值

5.请实现一个装饰器,限制该函数被调用的频率,如10秒一次

import time


def outter(func):

    def inner(*args, **kwargs):
        print('开始调用函数。。。')
        res = func(*args, **kwargs)
        time.sleep(10)
        print('函数调用结束。。。')
        return res

    return inner

@outter
def index():
    print('函数正在执行中。。。')

index()

6.什么是序列化?什么是反序列化?为什么要这么做?

序列化:
序列:字符串
序列化:其他数据类型转成字符串的过程
  序列化:其他数据类型转成字符串的过程
  反序列化:字符串转成其他数据类型

注意:
  写入文件的数据必须是字符串(二进制)
  基于网络传输的数据必须是二进制

7.什么是json与picjle的区别是什么?

json:可以和其他语言玩

pickle:只能和自己(python)玩

8.ATM的登录与注册功能,用户数据用json数据保存。

    with open(user_path, 'w', encoding='utf-8') as f:
        json.dump(user_dic, f, ensure_ascii=False)
        f.flush()

9.写一个扑克牌随机发牌游戏

飘三叶:

有bug,可取到重复的牌

import random

def fried_golden_flower():
    for i in range(0, 3):
        color = random.choice(['♥', '♠', '♦', '♣'])
        number = random.choice(['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'])
        a = color
        b = number
        point = namedtuple('扑克牌', ['color', 'number'])
        p = point(color, number)
        print(p, a+b)
        
fried_golden_flower()

斗地主:

from collections import namedtuple
import random

def fight_against_landlords():
    list = ['大鬼', '小鬼']
    color = ['♥', '♠', '♦', '♣']
    number = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
    for i in color:
        for n in number:
            list.append(i+n)
    # 打乱顺序
    random.shuffle(list)
    # 生成迭代器,避免取到重复的牌
    a = list.__iter__()
    for i in range(0,3):
        list_s = []  # 将发的17张牌放在此列表中
        for num in range(0, 17):
            list_s.append(a.__next__())
        print("玩家%s:%s" % (i+1, list_s))
    dizhupai = []
    for i in range(0, 3):
        dizhupai.append(a.__next__())
    print('地主牌:%s' % dizhupai)


fight_against_landlords()

10.爬虫正则

# 注意: 先敲课堂上的代码,理解并记录博客,再写作业! 
'''
1.subprocess模块的作用?
    subprocess 子进程模块
2.什么是包?包的作用是什么?
    包是一个带有__init__.py的文件夹,包也可以被导入,并且可以一并导入包下的所有模块。
3.如何防止模块被导入时自动执行测试功能。
        
        伪代码:
        if __name__ == '__main__':
                调用执行的函数()
    
4.请写出logging模块的使用步骤:
            # logging配置字典
            LOGGING_DICT = {...}
            
    1.配置日志的路径,项目的路径
    2.配置日志的文件(名字,创建日志文件)
    3.配置日志字典数据
    4.调用日志模块,并把字典数据当参数参数

5.请写出爬虫原理的4个过程?
    整个流程:
        1.发送请求:requests
        2.获取响应数据:对方机器直接返回
        3.解析并提取想要的数据:re
        4.保存提取后的数据:with open()保存
    我们需要做的:
        1.发送请求
        2.解析数据
        3.保存数据
    
6.什么是正则表达式与re模块?
    正则表达式:一种筛选匹配字符串的独立技术
    re模块:pycharm利用re模块,匹配字符串
    
7.使用正则表达式匹配出str1中的地址。
        source = '''
        <html><h1>www.baidu.com</h1></html>
        <html><h1>www.taobao.com</h1></html>
        <html><h1>www.jd.com</h1></html>
        <html><h1>www.oldboyedu.com</h1></html>
    '''
答案1:print(re.findall('www.(?:baidu|taobao|jd|oldboyedu).com', source))
结果:['www.baidu.com', 'www.taobao.com', 'www.jd.com', 'www.oldboyedu.com']
答案2:print(re.findall('www\..*com', source))
        
8.用正则过滤掉str3中的英文和数字,最终输出"张全蛋 广州"
        str3 = "not 404 found 张全蛋 99 广州"
不标准答案:print(re.findall('(?:张全蛋|广州)', str3))
结果:['张全蛋', '广州']
答案:print(re.findall('[^a-z:0-9:A-Z ]{2}', str3))
结果:['张全蛋', '广州']
9.复习今日之前的所有知识点!!!
'''

11.面向对象编程的优缺点是什么?

优点:可扩展性高
缺点:相对于面向过程复杂度高

12.对象的属性查找顺序是什么?

自己——类——报错
class Student:
    name = '张全蛋'
    def __init__(self, name):
        self.name = name
        
    def learn(self):
        print('learning...')

stu1 = Student('赵铁柱')
print(stu1.name)


# 结果:赵铁柱    优先查找自己

13.什么是继承?继承的目的?

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类(super),新建的类称为派生类或子类

14.python与期他语言的继承区别是什么?

python可以多继承,其他语言只能单继承

15.如何寻找继承关系?

mro(): 会把当前类的继承关系列出来

16.继承背景下对象属性的查找顺序是什么?

自己-->类->报错

17.什么是派生?如何重用父类的属性并派生?两种方式

第一种:super().__init方法
class Animal():
    def __init__(self, name, eat, run):
        self.name = name
        self.eat = eat
        self.run = run
        print(f'{self.name}会{self.eat}')
        print(f'{self.name}会{self.run}')

class Sunwukong(Animal):
    def __init__(self, name, eat, run, aa):
        super().__init__(name, eat, run)
        self.aa = aa
  
第二种:父类.__init__方法
class Animal():
    def __init__(self, name, eat, run):
        self.name = name
        self.eat = eat
        self.run = run
        print(f'{self.name}会{self.eat}')
        print(f'{self.name}会{self.run}')

class Sunwukong(Animal):
    def __init__(self, name, eat, run, aa):
        Animal.__init__(self,name, eat, run)
        self.aa = aa

18.什么是新式类与经典类?

- 新式类:
    1.凡是继承object的类或子孙类都是新式类。
    2.在python3中所有的类都默认继承object,都是新式类。

- 经典类:
    1.在python2中才会有经典类与新式类之分。
    2.在python2中,凡是没有继承object的类,都是经典类。

19.钻石继承下,经典类与新式类属性的查找顺序是什么?

20.下面这段代码的输出结果将是什么?请解释。

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)  #  1 1 1
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)  # 1 2 1
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)  # 3 2 3

# 结果:
1 1 1
1 2 1
3 2 3

21.下述代码新式类与新式类的查找顺序是什么?

class A(object):
    def test(self):
        print('from A')
class B(A):
    def test(self):
        print('from B')
class C(A):
    def test(self):
        print('from C')
class D(B):
    def test(self):
        print('from D')
class E(C):
    def test(self):
        print('from E')
class F(D, E):
    def test(self):
        print('from F')
    pass

# python3中校验:
        FD->DB->FE->EC->CA

# python2中校验:
        FD->DB->BA->FE->EC

22.什么是组合?为什么要使用组合?

组合指的是一个对象中,包含另一个或多个对象。

23.什么是封装?

隐藏对象的属性和实现细节,仅对外提供公共访问方式

24.什么是访问限制机制?

在内部在属性前加'__',使属性私有化。实际上是内部替换了变量名称   方法名   替换为:_类名__方法名

25.访问限制机制的优点?

1.让一些关键的数据,变成私有更加的安全
2.不是随意可以更改的
3.在属性,和方法前面加’__‘,变成私有,那么外界就不可以直接调用修改。
4.但是:在类的内部可以定义一个函数,方法调用修改。使用者直接调用这个函数就可以了。这个函数就是接口
5.可以在这个函数、方法加条件限制,而不是任意的改动

26.什么是property?为什么要使用property?

让使用者调用方式一致,是一个内置的装饰器。
使用了property内置装饰器之后,使用者调用方法时少了一个括号,导致看起来像获取某个方法,而不是加括号执行某个函数

27.输入半径,计算圆的面积、周长

第一种方式:类绑定

import math
class Circular():
    # 计算面积
    @classmethod
    def area(self,randius):
        res = math.pi * math.pow(randius, 2)
        print(f'面积为:{res}')
        
    #计算周长
    @classmethod
    def perimeter(self, randius):
        res = 2 * math.pi * randius
        print(f'周长为:{res}')

Circular.area(10)
Circular.perimeter(10)
# 结果:
面积为:314.1592653589793
周长为:62.83185307179586

第二种方式:对象绑定

import math
class Circular():
    def __init__(self, randius):
        self.randius = randius
    # 计算面积
    @property
    def area(self):
        res = math.pi * math.pow(self.randius, 2)
        print(f'面积为:{res}')

    # 计算周长
    @property
    def perimeter(self):
        res = 2 * math.pi * self.randius
        print(f'周长为:{res}')

# 生成对象
A = Circular(10)
# 执行
A.area
A.perimeter
# 结果:
面积为:314.1592653589793
周长为:62.83185307179586

28、使用abc模块定义一个Phone手机抽象类,让所有子类都继承手机抽象类,让不同牌子的手机都必须遵循抽象类手机打电话的步骤。

# @abc.abstractmethod子类必须按照父类的方法编写
import abc
class Phone():
    @abc.abstractmethod
    def call(self):
        pass

class Xiaomi(Phone):
    def call(self):
        print('小米手机正在打电话!')

class Iphone(Phone):
    def call(self):
        print('我是闪亮苹果BB机,正在打电话!')
# 产生对象
iphone = Iphone()
xiaomi = Xiaomi()
# 执行
iphone.call()
xiaomi.call()
# 结果:
我是闪亮苹果BB机,正在打电话!
小米手机正在打电话!

29 上传下载电影

服务端:

import socket
import json
import struct
import os

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
conn, addr = server.accept()


def unload():
    while True:
        try:
            hand_dict = conn.recv(4)
            len_dict = struct.unpack('i', hand_dict)[0]
            dict_json = conn.recv(len_dict)
            dict = json.loads(dict_json.decode('utf-8'))
            move_size = dict['move_size']

            accept_size = 0
            with open(dict['move_name'], 'wb')as f:
                while accept_size < move_size:
                    accept = conn.recv(1024)
                    f.write(accept)
                    accept_size += len(accept)
                print('上传成功!')

        except StopIteration as f:
            print(f)
            break


def load():
    while True:
        try:
            DATA_PATH = os.path.dirname(__file__)
            MOVE_PATH = os.path.join(DATA_PATH)
            # 把电影列表打包传给客户端
            move_list = os.listdir(MOVE_PATH)
            move_list_json = json.dumps(move_list).encode('utf-8')
            hand_dict = struct.pack('i', len(move_list_json))
            # 发送报头
            conn.send(hand_dict)
            # 发送json格式真实电影列表
            conn.send(move_list_json)

            # 接收客户选择要下载的电影编号  4个字节接受编号,足够
            choice = conn.recv(4)
            choice = int(choice.decode('utf-8'))
            # 根根选择,拿到电影名
            move_name = move_list[choice]
            # 拼接选择的电影路径
            move_name_path = os.path.join(MOVE_PATH, move_name)
            # 电影大小
            move_size = os.path.getsize(move_name_path)
            # 做成字典
            move_dict = {'move_name': move_name, 'move_size': move_size}
            # 序列化
            move_json = json.dumps(move_dict).encode('utf-8')
            hand_dict = struct.pack('i', len(move_json))

            # 发送报头,和json格式字典
            conn.send(hand_dict)
            conn.send(move_json)

            with open(move_name_path, 'rb')as f:
                for i in f:
                    conn.send(i)
                print('下载成功!')
        except StopIteration as f:
            print(f)
            break


def run():
    res = conn.recv(4)
    res = res.decode('utf-8')
    if res == '1':
        unload()
    elif res == '2':
        load()


run()

server.close()

客户端:

import socket
import json
import os
import struct

client = socket.socket()
client.connect(('127.0.0.1', 8080))


# 上传电影
def unload():
    while True:
        print('---下载电影---')
        # 拼接路径
        MOVE_PATH = os.path.join('D:\PS素材')
        move_list = os.listdir(MOVE_PATH)

        for index, move_name in enumerate(move_list):
            print(index, move_name)
        choice = input('请选择电影编号(q.退出):').strip()
        if choice == 'q':
            break
        if not choice.isdigit():
            print('输入数字!')
            continue
        choice = int(choice)
        if choice not in range(len(move_list)):
            print('不在范围!')
            continue
        move_name = move_list[choice]
        move_name_path = os.path.join(MOVE_PATH, move_name)
        move_size = os.path.getsize(move_name_path)
        move_dict = {'move_name': move_name, 'move_size': move_size}

        move_json = json.dumps(move_dict).encode('utf-8')
        hand_dict = struct.pack('i', len(move_json))

        client.send(hand_dict)
        client.send(move_json)

        with open(move_name_path, 'rb')as f:
            for i in f:
                client.send(i)
            print('上传成功!')

# 下载电影
def load():
    while True:
        print('---下载电影---')
        hand_dict = client.recv(4)
        len_dict = struct.unpack('i', hand_dict)[0]
        # 接收了json格式的列表
        dict_json = client.recv(len_dict)
        # 解码电影列表
        move_list = json.loads(dict_json.decode('utf-8'))
        # 打印列表,展示
        for index, move_name in enumerate(move_list):
            print(index, move_name)

        while True:
            choice = input('选择你要下载的电影编号 (q.退出):').strip()
            if choice == 'q':
                run()
            if not choice.isdigit():
                print('输入数字!')
                continue

            choice = int(choice)
            if choice not in range(len(move_list)):
                print('输入不规范!')
                continue
            # 如果输入规范,把用户选择的编号传给客户端
            choice = str(choice).encode('utf-8')
            client.send(choice)

            hand_dict = client.recv(4)
            len_dict = struct.unpack('i', hand_dict)[0]
            dict_json = client.recv(len_dict)
            dict = json.loads(dict_json.decode('utf-8'))
            move_size = dict['move_size']

            accept_size = 0
            with open(dict['move_name'], 'wb')as f:
                while accept_size < move_size:
                    accept = client.recv(1024)
                    f.write(accept)
                    accept_size += len(accept)
                print('下载成功!')
            continue


def run():
    while True:
        print('''
        1:【上传电影】
        2:【下载电影】
        q:退出
        ''')

        choice = input('请选择功能:').strip()

        if choice == '1':
            client.send(choice.encode('utf-8'))
            unload()
        elif choice == '2':
            client.send(choice.encode('utf-8'))
            load()
        elif choice == 'q':
            break

        else:
            print('输入不规范!')
            continue


if __name__ == '__main__':
    run()

30.二进制转其他字符类型:

int 其他进制转十进制
    a = int('0b1010011010', 2)
    b = int('0o1232', 8)
    c = int('0x29a', 16)
    print(a,b,c)
    # 结果: 666 666 666
bin 十进制转二进制
    aa = bin(666)
    print(aa)
    # 结果 :0b1010011010
oct 十进制转八进制
    bb = oct(666)
    print(bb)
    # 结果 :0o1232
oct 十进制转八进制
    bb = oct(666)
    print(bb)
    # 结果 :0o1232

31.decode、endoce

第一种:
    res = a.encode('utf-8')  # 编码
    print(res.decode('utf-8'))  # 解码
第二种:
    res1 = bytes(a, encoding='utf-8')  # 编码二进制
    res2 = str(res1, encoding='utf-8')  # 解码二进制

猜你喜欢

转载自www.cnblogs.com/guyouyin123/p/12150694.html