python基础四

"""
多继承:
    属性:
        类属性:
            子类可以继承所有父类中的类属性
        对象属性:
            __init__
            取决于继承顺序

    方法:
        子类可以继承所有父类中的非私有方法
        如果两个父类中有同名方法,取决于继承顺序

    多继承下super关键字的使用
    super搜索顺序取决于__mro__

    python3
        一律用的广度优先
    python2
        新式类:
            广度优先
        旧式类:
            深度优先


多态
    同样的方法名,根据调用对象的不同,执行效果不同
    前提:
        继承
        方法重写
抽象类:
    包含抽象方法的类

    如何创建抽象类
    from abc import ABCMeta,abstractmethod
    class Animal(metaclass = ABCMeta)
    @abstractmethod
    def xxx():
        pass

    特性:
        不能实例化
    作用:
        主要用于被子类继承
        可以约束子类的行为(要求子类必须重写父类中的抽象方法,如果不重写,子类依旧为抽象类)

魔法方法:
    一定场景下自动触发
    __str__
        打印对象
    __repr__
        打印对象
        %s:指定调用__str__
        %r:指定调用__repr__
    __call__
        把一个对象当方法调用的时候的,该方法会自动执行
    __new__:
        创建对象,系统分配内存空间的时候
    __init__
        对象初始化的时候会被调用(在__new__调用之后)
    __del__
        当一个对象被系统回收之前,会被调用

"""
class A:
    a = 10
class B:
    b = 20
class C(A,B):
    pass
c = C()
print(c.a)
print(c.b)
"""
彩票类:
	属性:
		彩票号码
		彩票价格
	行为:
		展示彩票信息
系统类:

	行为:
		生成彩票
		彩票开奖
人类:
	属性:
		名字
		金钱
		已购彩票
	行为:
		购买彩票
		兑奖
		剩余金钱展示
交互:
	实现张三花xx钱买了1注彩票,去兑奖,展示中奖结果,以及张三的剩余钱数

"""
import random
class Lottery:
    def __init__(self,a,b,c):
        self.price = 2
        self.nums = [a,b,c]
    def show_nums(self):
        print(f'号码:{self.nums}')
        return self.nums
class System:
    # 得到一注彩票
    def random_lottery(self):
        a = random.randint(0,9)
        b = random.randint(0,9)
        c = random.randint(0,9)
        return Lottery(a,b,c)# 匿名对象
    # 开奖
    def lottery_run(self,people):
        # 系统随机生成一组号码
        # 跟人拿过来的彩票进行对比
        pass
class Human:
    def __init__(self,name,money):
        self.name = name
        self.money = money
        self.lottery = None
    def buy_lottery(self):
        # 手选号码
        # 得到一个彩票对象,做为self.lottery的属性值
        pass
        print(f'{self.name}花{self.lottery.price}钱买了一注彩票:{self.lottery.nums}')
    # 兑奖
    def exchange(self):
        # 本质调用系统的开奖
        pass

    # 展示剩余钱数
    def show_left_money(self):
        print(f'剩余钱数:{self.money}')

"""
彩票类:
	属性:
		彩票号码
		彩票价格
	行为:
		展示彩票信息
系统类:

	行为:
		生成彩票
		彩票开奖
人类:
	属性:
		名字
		金钱
		已购彩票
	行为:
		购买彩票
		兑奖
		剩余金钱展示
交互:
	实现张三花xx钱买了1注彩票,去兑奖,展示中奖结果,以及张三的剩余钱数

"""
import random
class Lottery:
    def __init__(self,a,b,c):
        self.price = 2
        self.nums = [a,b,c]
    def show_nums(self):
        print(f'号码:{self.nums}')
        return self.nums
class System:
    # 得到一注彩票
    def random_lottery(self):
        a = random.randint(0,9)
        b = random.randint(0,9)
        c = random.randint(0,9)
        return Lottery(a,b,c)# 匿名对象
    # 开奖
    def lottery_run(self,people):
        # 系统随机生成一组号码
        lottery = self.random_lottery()
        print(f'开奖号码:{lottery.nums}')
        # 跟人拿过来的彩票进行对比
        if self.compare_lotterys(lottery,people.lottery):
            print('中奖200元,钱数增加')
            people.money += 200
        else:
            print('感谢你为福利事业做的贡献')
    # 单独比较两个对象
    def compare_lotterys(self,lottery1,lottery2):
       return sorted(lottery1.nums) == sorted(lottery2.nums)
class Human:
    def __init__(self,name,money):
        self.name = name
        self.money = money
        self.lottery = None
    def buy_lottery(self):
        # 手选号码
        a = int(input('请选择号码1'))
        b = int(input('请选择号码2'))
        c = int(input('请选择号码3'))
        # 得到一个彩票对象,做为self.lottery的属性值
        # 给当前的彩票属性进行赋值
        self.lottery = Lottery(a,b,c)
        self.money -= 2
        print(f'{self.name}花{self.lottery.price}钱买了一注彩票:{self.lottery.nums}')
    # 兑奖
    def exchange(self):
        # 本质调用系统的开奖
        system = System()
        system.lottery_run(self)

    # 展示剩余钱数
    def show_left_money(self):
        print(f'剩余钱数:{self.money}')

# 创建张三
people1 = Human('张三',100)
# 张三买彩票
people1.buy_lottery()
people1.exchange()


"""
__hash__
    求hash值的
    底层数据结构为hash表,
    hash()函数

    hash表存储数据的原理:
        1.计算哈希值,决定hash表中存储的位置
            __hash__
        2.与当前位置其他对象去(比较),如果相等,则不存储,不等,才存储进来
            __eq__

"""
print(hash('a'))

class Student:
    def __init__(self,id,name,age):
        self.id = id
        self.name = name
        self.age = age

    def __hash__(self):
        # 根据指定的元素计算哈希值,object中的hash是基于地址进行计算的
        return hash(self.id)
    # 按指定的内容去比较
    def __eq__(self, other):#
        return self.id == other.id



stu1 = Student(1001,'张三',19)
stu2 = Student(1001,'张三',19)
stu3 = Student(1001,'张三',19)
print(hash(stu1))
set1 = set()
set1.add(stu1)
set1.add(stu2)
set1.add(stu3)
# 思考? 可以存储几个对象进来?
print(set1)

"""
is:
    比较两个对象是否为同一个
==:
    本质调用__eq__
    用来比较两个对象内容是否一致

运算符重载问题:
    == -> __eq__
    >  ->  __gt__
    <
"""

print(1 == 2)
print('123' == '321')
class Dog:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        return self.name == other.name and self.age == other.age
    # def __add__(self, other):
    #     print('__add__被调用')
    #     return self.age + other.age

    # def __gt__(self, other):
    #     return True

dog1 = Dog('大壮',3)
dog2 = Dog('大壮',3)
print(dog1 == dog2)
print(dog1 is dog2)
# print(dog1 + dog2)
print(dir(object))
# print(dog1 > dog2)
"""
判断
isinstance()
issubclass()




isinstance
格式:isinstance(对象,类)
检测一个对象是否是某个类的实例,或者是其子类的实例

issubclass
格式: issubclass(被检测类,父类)
检测一个类是否是另外一个类的子类


__class__:
    特殊属性,作用:可以获取某个对象所属的类

注意:
    所有类都可以看成是 type<元类> 的对象



如果判断一个变量是否为int
"""
# a = eval(input('输入一个变量'))
# # 判断a是否为整型
# if type(a) == int:
#     print('整型')
# else:
#     print('不是整型')

class Human:
    pass
class Student(Human):
    pass


stu1 = Student()
print(isinstance(stu1,Student))
# print(type(stu1) == Student)
print(isinstance(stu1,Human))
# print(type(stu1) == Human)
print(isinstance(stu1,object))

print('----'*20)
print(issubclass(Student,Human))
print(issubclass(Student,Student))
print(issubclass(Student,object))

# print(type(stu1))
# print(type(int))
# print(type(str))
# print(type(object))

print(stu1.__class__)
print(issubclass(stu1.__class__,Human))






"""
反射方法:

    hasattr(obj,name)
    判断是对象obj中是否有名字为name的属性,返回 bool 值,如果有,返回True,没有返回False
        格式:hasattr(对象,'属性名')
    getattr
    getattr(obj,name)
        获取对象obj中,属性名为name的值,这个值有可能是方法



    delattr
    setattr

"""
class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def study(self):
        print('我爱学习')

stu1 = Student('xx',12)

print(dir(stu1))
# 判断对象是否包含某个属性
if hasattr(stu1,'age'):
    print('包含该属性')
else:
    print('没有该属性')
if hasattr(stu1,'study'):
    print('包含该方法')
    # 获取对象stu1中,名字为study的方法
    f = getattr(stu1,'study')
    print(type(f))
    print(f)
    f()

else:
    print('没有该属性')


"""
hasattr
getattr

setattr
    为某个对象的某个属性设置值
delattr
    删除某个对象的某个属性
"""
import time
import demo07_反射函数
# 面向对象
print(time.time())
# 基于反射,函数式编程
t = getattr(time,'time')
print(t())

# 基于反射获取到某个模块中的类
if hasattr(demo07_反射函数,'Student'):
    # 通过反射获取模块中Student类
    S = getattr(demo07_反射函数,'Student')
    print(S)
    stu1 = S('学生1',19)

    # 删除对象的属性
    # delattr(stu1,'age')
    del stu1.age
    print(dir(stu1))

    # 通过反射技术设置属性age的值
    # setattr(stu1,'age',20)
    # print(stu1.age)
    # print(getattr(stu1,'age'))

else:
    print('没有Student')



"""
生成器:
    什么是生成器?
        一遍循环一遍计算的机制

    列表的弊端:
        # 耗时:
        # 开销内存

    生成器可以实现什么?
        可以生成数据

    如何创建生成器(生成器的用法)
        1.g = (列表推导式)
        2.一个函数中,包含yield关键字
    如何使用生成器生成数据:
        1.next(g)
        2.g.__next__()
        3.g.send(argv)
            参数有要求:首次获取的时候,必须给None,非首次获取的时候,可以给任意参数
    注意:
        生成器生成数据只能从前往后,依次生成,如果超出范围,会导致StopIteration异常
        生成器具备可迭代性(可以使用for循环直接遍历)

    生成器的好处:
        效率更高
        更节约内存

    弊端:
        没有列表使用更方便

"""
import time
import sys
# start_time = time.time()
# # list1 = [x for x in range(1,10000001) if x % 2 == 0]
# g = (x for x in range(1,11) if x % 2 == 0)#[2,4,6,8,10]
# print(g)
# end_time = time.time()
# print(f'耗时:{end_time-start_time}秒')
# # print(f'占用内存:{sys.getsizeof(list1)/1024}k')
# print(f'占用内存:{sys.getsizeof(g)/1024}k')

# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# for i in g:
#     print(i)

def func1():
    for i in range(10):
        # print(i)
        yield i
        # yield 1

v = func1()
print(v)
# for i in v:
#     print(i)
# print(next(v))
# print(v.__next__())
print(v.send(None))
print(v.send(123))


"""

yield关键字作用:
    暂停函数(记录所有状态)


yield 协程

    多任务交替执行

g.send(None)

"""
# def gen():
#     print('a')
#     count = yield 1
#     # print('--->',count)
#     # print('b')
#     yield 2
# #注意打印结果
# g = gen()
# print(next(g))
# # print(g.send('123'))
# next(g)

# for i in g:
#     print(i)

import time
def get():
    while True:
        print('爬数据')
        yield
def deal():
    while True:
        print('处理数据')
        yield

g1 = get()
g2 = deal()

while True:
    next(g1)
    next(g2)
    time.sleep(0.5)

"""
魔法方法
    __hash__
        求hash值,
    __eq__
        做比较
        == 的本质

运算符重载:
    __eq__
        ==
    __add__
        +
    __ne__
        !=
    __gt__
        >

is 与 == 的使用
    is: 比较两个对象是否为同一个
    ==: 比较内容是否一致


关于类的操作函数
    isinstance(obj,cls)
        判断obj是否cls的对象或者是其子类的对象

    issubclass(cls1,cls2)
        判断cls1是否为cls2的子类(直接,间接,虚拟)


反射
    hasattr(obj,name)
        判断对象obj是否包含属性名/方法名为name的属性
        name要求必须是字符串
    getattr(obj,name[,default])
        获取对象obj,属性/方法名为name的值,如果有,则获取到对应的值,如果获取default

    setattr
        设置属性/方法
    delattr
        删除属性/方法

生成器
    定义:
        一遍循环一遍计算
    创建方式
        1.g = (推导式)
        2.包含yiele关键字的函数
    生成元素的方法
        1.next(g)
        2.g.__next__()
        3.g.send(args)
            首个元素args必须给None
            非首个元素,可以给任意参数
    好处:
        创建高效(节省空间,时间)
    弊端:
        没有索引,访问起来相对麻烦

"""

"""
2.编写程序实现乐手弹奏乐器。乐手可以弹奏不同的乐器从而发出不同的声音。
可以弹奏的乐器包括二胡、钢琴和小提琴。
实现思路及关键代码
1)定义乐器类(抽象类)Instrument,包括抽象方法makeSound()
2)定义乐器类的子类:二胡Erhu、钢琴Piano和小提琴Violin,
3)定义乐手类Musician,可以弹奏各种乐器play(instrument)
4)给乐手不同的乐器让他弹奏
"""
from abc import abstractmethod,ABCMeta
class Instrument(metaclass=ABCMeta):
    @abstractmethod
    def makeSound(self):
        pass
class Erhu(Instrument):
    def makeSound(self):
        print('二泉映月')
class Piano(Instrument):
    def makeSound(self):
        print('命运交响曲')
class Violin(Instrument):
    def makeSound(self):
        print('梁祝')
class Musican:
    def play(self,instrument):
        instrument.makeSound()

# m = Musican()
# erhu = Erhu()
# piano = Piano()
# violin = Violin()
# m.play(erhu)
# m.play(piano)
# m.play(violin)
"""
3.在一个模块中封装学生类,包含属性:名字,年龄,性别,方法:学习,睡觉
使用反射技术,完成对象的创建,属性的赋值,方法的调用
"""
import student
if hasattr(student,'Student'):
    Student = getattr(student,'Student')
    stu1 = Student('xx',18,'男')
    setattr(stu1,'gender','女')
    if hasattr(stu1,'sleep'):
        sleep = getattr(stu1,'sleep')
        sleep()





"""
4.使用两种方式创建可以生成10以内所有偶数的生成器,并使用相应方式展示生成数据。
"""
g = (i for i in range(1,11) if i % 2 == 0)
def func1():
    for i in range(1,11):
        if i % 2 == 0:
            yield i
# for i in g:
#     print(i)
#
# g1 = func1()
# print(next(g1))
"""
5.小明通过美团外卖叫了一份xx商家的外卖,外卖小哥很快将外卖送到了小明手里,并求小明给五星好评

类图 (UML)
使用图例描述出类与类之间的关系

用户类
    属性:
        名字
        地址
        联系方式
    行为:
        点外卖(平台)        
软件类App
    属性:
        平台名称
        商家列表
    行为:
        下单(商家)
        派单(骑手)
商家类
    属性:
        名称
        菜单
    行为:
        接单()

骑手类
    属性:
        名字
        电话
    行为:
        取餐(商家)
        送餐(用户)
        求好评(用户)
        
"""
# 用户类
class User:
    def __init__(self,name,address,tel):
        self.name = name
        self.address = address
        self.tel = tel
    # 通过某个软件,点外卖
    def take_out(self,app):
        # 选择一个商家
        print(f'{self.name} 通过{app.app_name} 在商家{app.merchant_list[0].name} 叫了一份外卖')
        app.place_order(app.merchant_list[0])
# 平台类
class App:
    def __init__(self,app_name):
        self.app_name = app_name
        # 商家列表
        self.merchant_list = [Merchant('北京饭店'),Merchant('建国饭店'),Merchant('国贸饭店')]
    # 平台为商家下单
    def place_order(self,商家):
        pass
        # 商家接单
    # 平台为骑手派单
    def send_order(self,骑手):
        pass
        # 骑手派单
# 商家类
class Merchant:
    def __init__(self,m_name):
        self.name = m_name
        self.menu_list = ['xx1','xx2']
    # 商家接单
    def get_order(self,app):
        pass

# 骑手类
class Rider:
    def __init__(self,name,tel):
        self.name = name
        self.tel = tel
    # 取餐
    def get_food(self,merchant):
        pass
    # 送餐
    def send_food(self,user):
        pass
    # 求好评
    def plese(self,user):
        pass

user = User('小明','北京市西城区天门广场',110)
app = App('美团外卖')




class Student:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def study(self):
        print('好好学习,天天向上')
    def sleep(self):
        print('好好睡觉,天天失眠')
"""
迭代器:
    迭代:
        迭代是访问集合元素的一种方式,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代
    可迭代性:Iterable
        可以for循环直接遍历
        是否实现了可迭代性协议(类内是否实现了__iter__()方法)

    迭代器:Iterator
        能够使用next()获取下一个元素的对象,都是迭代器对象
        迭代器协议:
            实现了__iter__以及__next__方法

        常见问题:
        1、具备可迭代性的对象是否一定是迭代器对象?
        2、生成器对象是否是迭代器对象

"""
# list1 = [1,2,3]
# for i in list1:
#     print(i)
# a = 10
# for i in a:
#     print(i)

# print(dir(list))
# print('__iter__' in dir(list))
# # print(dir(int))
# print('__iter__' in dir(int))
# print('__iter__' in dir(str))
# print('__iter__' in dir(dict))

from collections.abc import Iterable
from collections.abc import Iterator
# list1 = [1,2,3]
# # 判断是否具备可迭代性
# print('__iter__' in dir(list))
# print(isinstance(list1,Iterable))
#
# # 判断是否为迭代器对象
# print('__iter__' in dir(list) and '__next__' in dir(list))
# g = (x for x in range(5))
# print(isinstance(g,Iterator))


# r = range(0,10,1)
# for i in r:
#     print(i)
#r 是否具备可迭代性,是否为迭代器对象
# print(isinstance(r,Iterator))

# 模拟实现range类

# class MyRange:
#     def __init__(self,start,stop,step=1):
#         self.start = start
#         self.stop = stop
#         self.step = step
#     def __iter__(self):
#         print('__iter__被调用')
#         while self.start < self.stop:
#             yield self.start
#             self.start += self.step
#
# mr = MyRange(1,10,1)
# for i in mr:
#     print(i)

class MyRange:
    def __init__(self, start, stop, step=1):
        self.start = start
        self.stop = stop
        self.step = step
    def __iter__(self):
        return self
    def __next__(self):
        if self.start < self.stop:
            self.start += self.step
            return self.start - self.step
        raise StopIteration

mr = MyRange(1,5)
# print(next(mr))
# print(next(mr))
# print(next(mr))
# print(next(mr))
# print(next(mr))
for i in mr:
    print(i)
next(mr)







"""
闭包函数:
    本质:函数
使用场景:
    函数式编程
    为装饰器的使用做铺垫

作用域:
    LEGB
闭包的定义:
    1.函数嵌套定义(外部函数嵌套内部函数)
    2.在内部函数中使用外部函数中定义的变量
    3.外部函数必须要有返回值(返回内部函数名)

闭包函数的作用:
    ?





"""
def funcOut():
    a = 10
    def funcIn():
        nonlocal a
        a += 1
        print(a)
    # 验证是否为闭包函数
    print(funcIn.__closure__)
    # 返回内部函数名
    return funcIn

f = funcOut()
# print(f)
# f()

"""
闭包的作用:
    可以在不修改一个函数源代码的前提下,给它增加新的功能
"""
import time
import random

def funcOut(func):
    def funcIn():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f'耗时:{end_time-start_time}秒')
    return funcIn
def func1():
    # print('我是模拟的下载功能')
    for i in range(1,11):
        print(f'下载进行中{i*10}%')
        time.sleep(random.random())
    else:
        print('下载完成')
# start_time = time.time()
# func1()
# end_time = time.time()
# print(f'耗时:{end_time-start_time}秒')
func1 = funcOut(func1)
func1()

"""
闭包:
    可以不修改源码的前提下增加新的功能

    日志系统:
    1. 为功能func1增加日志功能
        将访问信息(访问时间,访问功能)存储到文件

    开闭原则:

装饰器:
    闭包函数
    只能修饰函数

"""
import time

# 封装成日志功能
def write_log(func):
    # 创建并打开文件
    f = open('log.txt', 'a', encoding='utf-8')
    # 访问时间
    time_str = time.asctime()
    # 访问的功能名
    func_name = func.__name__
    # 将内容写入文件
    f.write(time_str + '\t' + func_name + '\n')
    # 关闭文件
    f.close()
#
# def func1():
#     write_log(func1)
#     print('功能1')
# def func2():
#     write_log(func2)
#     print('功能2')
#
# func1()
#
# func2()

def funcOut(func):
    def funcIn():
        write_log(func)
        func()
    return funcIn
@funcOut   # func1 = funcOut(func1)
def func1():
    print('功能1')
@funcOut # func2 = funcOut(func2)
def func2():
    print('功能2')
# func1 = funcOut(func1)
func1()
# func2 = funcOut(func2)
func2()
"""
装饰器用来装饰函数
    先搞定闭包
思考:
    一个函数能够同时有多个装饰器(理解装饰顺序)

注意:
    如果被装饰的函数有返回值,要求闭包函数的内部函数必须有对应的返回值

"""
def funcOut2(func):
    print('funcOut2')
    def funcIn2():
        print('funcIn2')
        return '$'+func()+'$'
    return funcIn2
def funcOut1(func):
    print('funcOut1')
    def funcIn1():
        print('funcIn1')
        return '《'+func()+'》'
    return funcIn1

@funcOut1   #bookName = funcOut1(bookName)
@funcOut2   #bookName = funcOut1(bookName)
def bookName():
    return '西游记'

# bookName = funcOut1(bookName)

print(bookName())  #    西游记



"""
如果被装饰的函数有参数,要求闭包中的内部要有对应个数的参数

"""
import time
def write_log(func):
    # 创建并打开文件
    f = open('log1.txt', 'a', encoding='utf-8')
    # 访问时间
    time_str = time.asctime()
    # 访问的功能名
    func_name = func.__name__
    # 将内容写入文件
    f.write(time_str + '\t' + func_name + '\n')
    # 关闭文件
    f.close()

def funcOut(func):
    def funcIn(a,b):
        write_log(func)
        return func(a,b)
    return funcIn

@funcOut # add = funcOut(add)
def add(a,b):
    return a + b
print(add(1,2))


"""
1.迭代器
    迭代:

    可迭代性:Iterable
        引入可迭代性类
            from collections.abc import Iterable
        __iter__
        如何判断是否具备可迭代性:
            1.'__iter__' in dir(obj)
            2.isinstance(obj,Iterable)
        具备可迭代性的元素可以使用for循环直接遍历
    迭代器(Iterator)
        from collections.abc import Iterator
        实现了迭代器协议:
            __iter__()
            __next__()
        可以通过next()访问下个元素
        1.具备可迭代性是否就是迭代器?
        2.生成器是否一定是迭代器

        判断某个对象是否为迭代器对象:
            1. '__iter__' in dir(obj) and '__next__' in dir(obj)
            2. isinstance(obj,Iterator)
        for循环
            调用__iter__方法以及__next__

    函数
        作用: 可以将一个具备可迭代性的对象,转换为迭代器对象
        iter(iterable)->Iterator

2.闭包
    本质:函数
    1.函数嵌套定义
    2.内部函数使用外部函数中的变量
    3.外部函数返回内部函数名

    测试闭包函数
    __closure__

    作用:
        1.主要用于函数式编程
        2.为装饰器做铺垫
        3.可以使用闭包实现不修改功能源码的前提下,添加新功能

3.装饰器
    语法糖的语法:
    @闭包外部函数名
    用来装饰函数
    本质:
        函数

    通用装饰器
    def funcOut(func):
        def funcIn(*args,**kwargs):
              return func(*args,**kwargs)
        return funcIn
    
"""
from collections.abc import Iterable,Iterator
list1 = [1,2,3]
print(isinstance(list1,Iterable))
# 使用iter(iterable) 可以将list1转换成迭代器对象
list1 = iter(list1)
print(isinstance(list1,Iterator))
print(next(list1))


"""
2.封装一个类,可以通过for循环直接打印指定范围内的质数
class IntegerRange():
    def __init__(self,start,end,step):
        pass
    def __iter__(self):
       	pass
例如:
for i in IntegerRange(2,20,1):
	print(i)
可以依次打印出2,3,5,7,11...等全为质数的数字
"""
class IntegerRange:
    def __init__(self,start,end,step=1):
        self.start = start
        self.end = end
        self.step = step

    def is_prime_number(self,n):
        for i in range(2,n):
            if n % i == 0:
                return False
        return True

    def __iter__(self):
        while self.start < self.end:
            if self.is_prime_number(self.start):
                yield self.start
            self.start += self.step

r = IntegerRange(2,10)
for i in r:
    print(i)

"""
3.封装一个模拟下载函数,并使用装饰器完成下载函数耗时的统计
"""
import random
import time

def funcOut(func):
    def funcIn(*args,**kwargs):
        start_time = time.time()
        v = func(*args,**kwargs)
        end_time = time.time()
        print(f'完成功能{func.__name__} 耗时:{end_time-start_time}秒')
        return v
    return funcIn

@funcOut
def download():
    for i in range(1,11):
        time.sleep(random.random())
        print(f'下载完成{i*10}%')

download()


"""
4.使用两种方式创建可以生成10以内所有偶数的生成器,并使用相应方式展示生成数据。
"""
g = (i for i in range(1,11) if i % 2 == 0)
def func1():
    for i in range(1,11):
        if i % 2 == 0:
            yield i
# for i in g:
#     print(i)
#
# g1 = func1()
# print(next(g1))
"""
5.小明通过美团外卖叫了一份xx商家的外卖,外卖小哥很快将外卖送到了小明手里,并求小明给五星好评

类图 (UML)
使用图例描述出类与类之间的关系

用户类
    属性:
        名字
        地址
        联系方式
    行为:
        点外卖(平台)        
软件类App
    属性:
        平台名称
        商家列表
    行为:
        下单(商家)
        派单(骑手)
商家类
    属性:
        名称
        菜单
    行为:
        接单()

骑手类
    属性:
        名字
        电话
    行为:
        取餐(商家)
        送餐(用户)
        求好评(用户)
        
"""
# 用户类
class User:
    def __init__(self,name,address,tel):
        self.name = name
        self.address = address
        self.tel = tel
    # 通过某个软件,点外卖
    def take_out(self,app):
        # 选择一个商家
        print(f'{self.name} 通过{app.app_name} 在商家{app.merchant_list[0].name} 叫了一份外卖')
        # 调用软件的下单功能
        app.place_order(app.merchant_list[0],self)
# 平台类
class App:
    def __init__(self,app_name):
        self.app_name = app_name
        # 商家列表
        self.merchant_list = [Merchant('北京饭店'),Merchant('建国饭店'),Merchant('国贸饭店')]
    # 平台为商家下单
    def place_order(self,merchant,user):
        # 商家接单
        merchant.get_order(self)
        # 创建骑手
        rider = Rider('张三',123)
        self.send_order(rider,merchant,user)
    # 平台为骑手派单
    def send_order(self,rider,merchant,user):
        print(f'平台已派单给骑手:{rider.name}')
        # 骑手去取餐
        rider.get_food(merchant,user)
# 商家类
class Merchant:
    def __init__(self,m_name):
        self.name = m_name
        self.menu_list = ['xx1','xx2']
    # 商家接单
    def get_order(self,app):
#         print(f'商家{self.name} 已接收来自平台{app.app_name}的订餐')
#
# # 骑手类
class Rider:
    def __init__(self,name,tel):
        self.name = name
        self.tel = tel
    # 取餐
    def get_food(self,merchant,user):
        print(f'骑手{self.name} 前往商家{merchant.name} 取餐中')
        self.send_food(user)
    # 送餐
    def send_food(self,user):
        print(f'骑手{self.name} 为用户{user.name} 送餐中')
    # 求好评
    def plese(self,user):
        pass

# user = User('小明','北京市西城区天门广场',110)
# app = App('美团外卖')
# user.take_out(app)







"""
类的组成:
    属性:
        类属性/类变量
        对象属性/成员属性/成员变量
    行为:
        对象方法/成员方法
        类方法
        静态方法

类属于与成员属性:
    1.定义位置不同:
        类属性定义在类内,方法外
        对象属性定义在__init__方法内

    2.内存中存储的份数不同
        类属性:唯一一份
        对象属性:每个对象都有属于自己的一份

    3.所有者不同:
        类属性:
            属于类
        对象属性:
            属于对象
    4.访问方式不同:
        类属性:
            获取值:
                类名.类属性
                对象名.类属性
            设置值:
                类名.类属性
        对象属性:
            读写:
                对象名.属性名
    5.生命周期不同
        类属性:
            程序周期
        对象属性:
            对象创建时,出生,对象被系统回收时,结束

类方法:
    定义:
        需要使用@classmethod修饰
        有一个必需参数cls
    调用:
        类名.类方法()
        也可以使用对象调
        对象.类方法()

静态方法
    定义在类内的一个函数
    @staticmethod
    可以不用有任何参数
    调用:
        类名.静态方法()
        对象.静态方法()

"""
class Student(object):
    # 类属性
    cls_id = 102
    country = 'China'
    def __init__(self,name,age):
        self.name = name
        self.age = age

    @classmethod
    def cls_method(cls):
        print('我是类方法')
        print(cls)
        print(cls.cls_id)
    @staticmethod
    def static_method():
        print('我是静态方法')

stu1 = Student('峰哥',40)# Student.__new__().__init__()
#类属性的访问 读
print(Student.cls_id)
print(stu1.cls_id)

# 类属性的访问  写
Student.cls_id = 101
# 为对象动态添加属性
stu1.cls_id = 105

# del stu1

print(Student.cls_id)

# 调用类方法
Student.cls_method()
# 使用对象调用类方法
stu1.cls_method() # stu1.__class__.cls_method()

#调用静态方法
Student.static_method()
stu1.static_method()


"""
IO操作
文件操作:
    文件的分类:
        广义:
        狭义:
    文件的作用:
        数据持久化


    传统文件的操作:
        1.打开文件
        2.读写操作
        3.关闭文件

    写:
        课下查阅:
            绝对路径
            相对路径
        将内存中的数据->文件
        绝对路径:
            E:\offcn\授课班级\9.基地系统0902班\Day14代码\demo01_知识回顾.py
        相对路径:
            demo02.py
        f =  open('demo02.py','打开方式','文件编码方式')
        f.write('字符串内容')

    读:
        从文件中读取出来->内存
        read(n)
            读取指定长度n,如果不指定长度,默认读取所有
        readline()
            只读取一行
        readines()
            读取所有行,存储到列表中


# 循环录入一首诗,存储到文件中

"""
# 将一首诗写入到文件中
def poem_write():
    # 打开文件
    f = open('poem.txt','a',encoding='utf-8')
    for i in range(1,5):
        s = input(f'请输入第{i}句')
        # 将字符串s的内容写入到文件f中
        f.write(s+'\n')
    else:
        # 关闭文件
        f.close()
# poem_write()

def poem_read():
    f = open('poem.txt', 'r', encoding='utf-8')
    # s = f.read(5)
    # s = f.readline()
    s = f.readlines()
    print(s)
    f.close()

poem_read()
"""
文件的打开
    mode:  r  w  a
    读写:
        r+
        w+
        a+
    操作图片,音频,视频...
    rb
    wb

文件的读写
    read
    readline
    readlines

文件的关闭
f.close()

逐行读取文件的方式:
    for s in f:
        print(s)

    -----------

    s = f.readline()
    while s != '':
        print(s)
        s = f.readline()

文件的复制:
    1.读取目标文件中的数据
        打开目标文件
        读取所有内容

    2.将读取到的数据写入新文件中  (注意新文件名的处理)
        打开新文件
        将读取到的内容写入到新文件中

    关闭所有文件

    def copyfile(oldfile):
        pass

"""
# f = open('poem.txt',mode='r',encoding='utf-8')
# s = f.read(5)
# print(s)
# # 在之前读取结束的位置,继续读取
# s = f.read(5)
# print(s)
# f.close()

# 循环读取逐行读取某个文件中所有的内容
f = open('demo01_知识回顾.py','r',encoding='utf-8')
# for s in f:
#     print(s,end='')
# f.close()

s = f.readline()
while s != '':
    print(s,end='')
    s = f.readline()
f.close()


"""
完成某个文件的复制(读写),新文件名的处理


123.txt.py
123.txt-副本.py

对图片复制的注意事项
    打开方式:  rb
    写入方式:   wb
    不需要指定编码格式
"""
def copyfile(oldfile):
    # 读取旧文件内容
    with open(oldfile,'r',encoding='utf-8') as f:
        s = f.read()
        # 新文件名
        # index = oldfile.rfind('.')
        # oldname = oldfile[:index]
        # newname = oldname+'-副本'
        # # 包含.的后缀
        # suffix = oldfile[index:]
        # newname += suffix

        # newname = oldfile[:oldfile.rfind('.')] + '-副本' + oldfile[oldfile.rfind('.'):]
        #
        t = oldfile.rpartition('.')
        newname = t[0]+'-副本'+t[1]+t[2]
        # print(newname)
        # 打开新文件
        with open(newname,'w',encoding='utf-8') as f1:
            # 写入操作
            f1.write(s)
# copyfile('poem.txt')


# 图片复制
def copyfile1(oldfile):
    # 读取旧文件内容
    with open(oldfile,'rb') as f:
        s = f.read()
        t = oldfile.rpartition('.')
        newname = t[0]+'-副本'+t[1]+t[2]
        # print(newname)
        # 打开新文件
        with open(newname,'wb') as f1:
            # 写入操作
            f1.write(s)

copyfile1('bird1.png')
"""
重命名文件
    os.rename(src,dst)
    os.rename('123.txt','124.txt')
删除文件
    os.remove(path)
    os.remove('123.txt')
创建目录
    os.mkdir()
创建多级目录
    os.makedirs()
删除目录
    os.rmdir()
删除多级目录
    os.removedirs()
获取当前目录
    os.getcwd()
修改所在目录
    os.chdir()
---------------------
判断文件是否存在
os.path.exists()
判断是否为文件
os.path.isfile()
判断是否为目录
os.path.isdir()
获取绝对路径
os.path.abspath()
判断是否为绝对路径
os.path.isabs()
获取路径的最后部分
os.path.basename()
获取父级路径
os.path.dirname()
获取文件夹内的子文件
os.listdir()
获取文件大小
os.path.getsize(file)

"""
import os
# 重命名
# os.rename('bird1.png','bird2.png')
# os.rename('bird2.png','bird1.png')
# 删除文件
# os.remove('bird1-副本.png')
# 创建文件夹
# os.mkdir('a')
# 删除文件夹
# os.rmdir('a')

# 创建嵌套文件夹
# os.makedirs('a/b/c')
# os.rmdir('a')
# 删除嵌套文件夹
# os.removedirs('a/b/c')

# 修改默认工作目录
# os.chdir('E:\offcn\授课班级\9.基地系统0902班')
# print(os.getcwd())
# os.mkdir('a')

"""
判断文件是否存在  *
    os.path.exists()
判断是否为文件 *
    os.path.isfile()
判断是否为目录 *
    os.path.isdir()
获取绝对路径
    os.path.abspath(path)
判断是否为绝对路径
    os.path.isabs()
获取路径的最后部分
    os.path.basename()
获取父级路径
    os.path.dirname()
获取文件夹内的子文件 *
    os.listdir(path)
获取文件大小
    os.path.getsize(file)

需求:
    统计从入学到现在你写的代码行数

"""
import os
# if os.path.exists('123.txt'):
#     f = open('123.txt', mode='r')
#     f.read()
#     f.close()
# else:
#     print('文件不存在')

path = '123.txt'
# if os.path.isfile(path):
#     print(f'{path} 为文件')
#     f = open(path)
#     print(f.read())
#     f.close()
# elif os.path.isdir(path):
#     print(f'{path} 为目录')
# else:
#     print('其他')

# 获取绝对路径
# path_abs = os.path.abspath(path)
# print(path_abs)
# # 判断路径是否为绝对路径
# print(os.path.isabs(path))
# print(os.path.isabs(path_abs))

# path1 = 'E:\offcn\授课班级\9.基地系统0902班\Day14代码\demo01_知识回顾.py'
# print(os.path.basename(path1))
# print(os.path.dirname(path1))

# path2 = 'E:\offcn\授课班级\9.基地系统0902班\Day14代码'
# filenames = os.listdir(path2)
# # print(filenames)
# for f in filenames:
#     print(f)

# 展示某个文件夹内所有的文件名
def showfiles(dirpath):
    # 获取文件夹内所有的子文件
    files = os.listdir(dirpath)
    for f in files:
        newpath = dirpath+'/'+f
        #判断f是文件还是文件夹
        if os.path.isfile(newpath):
            # 如果是python文件
            if newpath.endswith('.py'):
                print(newpath)
        elif os.path.isdir(newpath):
            showfiles(newpath)

path = 'E:\offcn\授课班级\9.基地系统0902班'
showfiles(path)

"""
统计某个文件夹内的代码行数
1.找出文件夹所有的.py文件
2.所有文件中代码行数累加(统计单个文件中的代码行数)

"""
import os
# dirPath = 'E:\\offcn\\授课班级\\9.基地系统0902班'
# dirpath = r'E:\offcn\授课班级\9.基地系统0902班'
dirPath = 'E:/offcn/授课班级/9.基地系统0902班'

# 存储所有代码行数
count = 0
count_list = []
def get_lines(file):
    # 记录文件代码行数
    temp = 0
    f = open(file,'r',encoding='utf-8')
    for s in f:
        temp += 1
    return temp

def showFiles(dirpath):
    # 文件夹内的所有子文件
    files = os.listdir(dirpath)
    # 遍历所有子文件
    for f in files:
        # 子文件的路径为之前文件夹路径+'/'+当前文件名
        newpath = dirpath + '/' + f
        # 判断新路径是否为文件
        if os.path.isfile(newpath):
            # 是否为py文件
            if newpath.endswith('.py'):
                # print(newpath)
                c = get_lines(newpath)
                # 将数量累加到count中
                count_list.append(c)
        elif os.path.isdir(newpath):
            showFiles(newpath)

showFiles(dirPath)
print(f'代码总行数:{sum(count_list)}')





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值