文章目录
博客cPen_web
知识点1 Python元类
·元类就是用来创建类的类。
type创建类
type就是Python的内建元类,我们也可以创建自己的元类。
示例1:type是一切类的元类
class A:pass
a1 = A()
print(type(a1)) # 注:使用type查看属于哪个类创建的
#结果为 <class '__main__.A'>
print(type(A)) # 注:一切类的元类都是 type type查看属于哪个类创建的
#结果为 <class 'type'> # 注:type 可以创建类
示例2:type与object
class Animal():
def __init__(self, name):
self.name = name
def eat(self):
print("i am eating...")
class Dog(Animal):
def eat(self):
print("dog is eating...")
#面向对象里有2种关系
#1、继承关系,父类子类的关系 继承关系中object是所有类的父类,是最顶层的基类
#2、示例与类的关系,创建关系 type就是最顶层的类,就是元类
dog = Dog("peiqi")
print(type(dog)) # 注:Dog类创建的 type查看属于哪个类创建的
#结果为 <class '__main__.Dog'>
print(type(Dog)) # 注:type创建的
#结果为 <class 'type'>
print(type(type)) # 注:type创建的
#结果为 <class 'type'>
#没有指定的话 都是type创建的
print(Dog.__bases__) # 注:看类的父类
#结果为 (<class '__main__.Animal'>,)
print(Animal.__bases__) # 注:__bases__查看属于哪个类的基类(即子类)
#结果为 (<class 'object'>,)
print(object.__bases__) # 注:object是所有类的父类
#结果为 ()
print(type.__bases__)
#结果为 (<class 'object'>,)
###type与object
#相当于鸡生蛋 先有鸡,还是先有蛋
# object = type() # 注:object是type创建的 type是元类
# class type(object) # 注:type继承object object是基类
示例3:使用type语法创建类
###使用type去创建类
#Python class创建类时 底层 实际使用 type去创建的
#不常用
class Animal():
def __init__(self, name):
self.name = name
def eat(self):
print("i am eating...")
def eat(self): # 注:属性/方法 写在外面
print("dog is eating...")
def __init__(self, name):
self.name = name
###type语法创建类,第1个参数是 类名,第2个参数 是继承关系(元组形式),第3个参数是 属性和方法(字典形式)
Dog = type("Dog",(Animal,),{"eat":eat}) # 注:使用type语法去创建类
dog = Dog("peiqi")
dog.eat()
#结果为 dog is eating...
#创建Animal类
Animal = type("Animal",(object,),{"eat":eat,"__init__":__init__})
编写元类
元类的主要目的就是为了当创建类时能够自动地改变类
·拦截类的创建
·修改类,返回修改之后的类
指定元类
·默认元类为type
示例4:自定义元类
###自定义元类
class MyMeta(type): # 注:继承type
def __init__(self, *args):
print("test my metaclass") # 注:初始化时输出
class Foo(metaclass=MyMeta): # 注:默认参数是type 使用MyMeta创建Fool
def __init__(self):
print("Fool__init__")
#结果为 test my metaclass
print(Foo.__bases__) # 注:Foo的__bases__是 object
#结果为 (<class 'object'>,)
示例5:元类可以规定类创建时候的一些行为
###元类可以规定类创建时候的一些行为
#注:拦截类创建的,对类设置做规范时
class MyMeta(type): # 注:继承type
def __new__(cls, name, bases, attrs): # 注:在__new__里面管理创建它 需要接收参数 这样传递(因为要把attrs捞出来判断)(或者可变长位置参数传递)
if "name" not in attrs:# 注:属性是字典类型的参数 type创建需要传递三个变量
raise TypeError("必须设置属性name")
attrs["test"] = "my mate test"
return type.__new__(cls, name, bases, attrs) # 注:元类里使用type的__new__去返回创建 把这些参数传递进去
# 注:不可能自己创建__new__的方法,使用type的__new__去创建
class A(metaclass=MyMeta): # 注:用自定义元类去创建
# pass
name = "wy"
#结果为 raise TypeError("必须设置属性name") # 注:A类中没有设置name属性时
# TypeError: 必须设置属性name
a = A() # 注:A的父类是object
print(a.test)
#结果为 my mate test
#把传进来的属性 先交给MyMeta去创建/添加 最后再交给type去创建
示例6:自定义元类,为每个类创建一个func方法,这个方法输出当前创建的类有哪些属性
#自定义元类,为每个类创建一个func方法,这个方法输出当前创建的类有哪些属性
class MyMeta(type):
def __new__(cls, name, bases,attrs):
attrs["func"] = cls.func # 注:attrs添加当前类的func
return type.__new__(cls,name,bases,attrs) # 注:交给type去创建
def func(self): # 注:添加普通属性 换成self好理解
return dir(self) # 注:返回当前类的属性
class A(metaclass=MyMeta): # 注:指定元类metaclass=MyMeta
age = 10
a = A()
print(a.func())
#结果为 ['__class__',………… 'age', 'func']
# 元类的主要目的就是为了当创建类时能够自动地改变类
# ·拦截类的创建
# ·修改类,返回修改之后的类
元类的主要目的就是为了当创建类时能够自动地改变类
·拦截类的创建
·修改类
·返回修改之后的类
知识点2 抽象基类
·抽象基类提供了逻辑和实现解耦的能力,即在不同的模块中通过抽象基类来调用
示例:抽象基类
###抽象基类 定义了接口规范
#子类必须实现抽象基类里的抽象方法
from abc import ABC, abstractclassmethod # 注:使用abc模块实现抽象基类的抽象方法
class Animal(ABC): #注:定义抽象基类
@abstractclassmethod
def eat(self): # 注:抽象方法
pass # 注:抽象方法不需要具体的实现
class Dog(Animal):
# pass
def eat(self):
print("dog is eating...")
dog = Dog() # 注:报错 不能实例化(子类不实现eat()抽象方法)
#结果为 TypeError: Can't instantiate abstract class Dog with abstract methods eat
dog.eat()
#结果为 dog is eating...
# a = Animal() #注:报错 抽象基类不可以实例化
#结果为 TypeError: Can't instantiate abstract class Animal with abstract methods eat
练习3 回合制对战游戏
# 回合制对战游戏
# ·创建角色:名字、性别、血量、装备 ·战斗
# ·创建房间: ·装备-防弹衣
# ·角色可加入房间 ·血量默认100
# ·房间内的人可互打 ·正常被攻击-10滴血
# ·房间上限2人 ·有防弹衣-5滴血
# https://blog.csdn.net/qq_45745649/article/details/104567674
示例
class Role():
def __init__(self,name,sex,blood=100,body_armor=None):
self.name = name
self.sex = sex
self.blood = blood
self.body_armor = body_armor
self.room = None
def attack(self,other):
if self.room == other.room: # 注:同一房间
if self != other: # 注:不同的人
if self.blood > 0 and other.blood > 0:
reduce_blood = 5 if other.body_armor else 10
# 注:body_armor为假 返回10(没有设置防弹衣)
other.blood -= reduce_blood
print(f"{self.name}攻击{other.name} {reduce_blood}点血量\t{self.name}当前血量:{self.blood}\t{other.name}当前血量:{other.blood}")
else:
print("其中一方已死亡,不能攻击")
exit()
else:
print("你不能攻击自己")
else:
print("攻击对象,不在同一个房间")
class Room():
def __init__(self,name):
self.member = []
self.name = name
def join(self,role):
if role.room == None:
# 注:在角色的类里定义的属性room
if len(self.member) < 2:
self.member.append(role)
# 注:member房间的属性,房间只能加2个人 所以<2
role.room = self.name
# 注:达到条件,定义角色加入到 某个房间
else:
print("此房间已满")
else:
print("此角色已经加入房间了")
role_dict = {} # 存放初始化实例 # 注:存放名字和对象的关系
room_dict = {} # 存放初始化实例
while True:
print("请选择:1.创建角色\t2.创建房间\t3.加入房间\t4.开始战斗\t5.退出")
enter_number = input("请输入你的选择\t")
if enter_number.isdigit():
enter_number = int(enter_number)
if 1 <= enter_number <=5:
if enter_number == 1:
name, sex = input("请输入角色的姓名与性别,空格隔开\n").split()
#注:split()是为了 分割 将字符 赋给2个变量
role_dict[name] = Role(name, sex)
def_blood = input("输入自定义血量\n")
if def_blood.isdigit():
role_dict[name].blood = int(def_blood)
print(f"自定义成功,用户{name}当前血量{role_dict[name].blood}")
else:
print(f"自定义失败,用户{name}当前血量{role_dict[name].blood}")
wear_body_armor = input("输入y装备防弹衣\n")
if wear_body_armor == "y":
role_dict[name].body_armor = 1
elif enter_number == 2:
name = input("请输入房间的名字\n")
room_dict[name] = Room(name)
# 注:创建好的对象(实例化对象) 保存在字典里
elif enter_number == 3:
print(f"当前角色有{role_dict.keys()},当前房间有{room_dict.keys()}")
role_name, room_name = input("请输入要加入的角色和房间名,空格隔开\n").split()
# 注:这里可以做1个判断 (考虑到各种情况)
room_dict[room_name].join(role_dict[role_name])
# 注:从字典 取出房间对象,调用房间对象的join()方法
elif enter_number == 4:
print(f"当前房间有{room_dict.keys()}")
room_name = input("请输入房间的名字\n") # 注:选择房间
if len(room_dict[room_name].member) == 2:
# 注:len()==2 这是保证房间里有2个人 才能对打
while True:
room_dict[room_name].member[0].attack(room_dict[room_name].member[1])
room_dict[room_name].member[1].attack(room_dict[room_name].member[0])
# 注:通过字典获取房间实例对象,member是房间的属性
# 注:为什么房间实例能获取到创建角色类的对象?因为选项3 是角色类属性 加入 房间member属性,保证了这一步能调用成功实例化对象
else:
print(f"房间{room_name}人数不足2人,对战失败!")
continue
elif enter_number == 5:
print("退出对战")
break
else:
print("输入错误,请输入1-5选择操作!")
else:
print("输入错误,请输入1-5选择操作!")
#用while True循环,不要用return相互调用
练习4 模拟ATM
#模拟ATM
#1、创建ATM
#ATM里的总金额
#ATM可向里面加钱
#ATM里的钱取出来
#2、创建账户去取钱
#账户属性 名称、余额、密码
#账户要选择1台ATM进行操作
#可以取钱、存钱、查询余额
示例1
class Atm():
def __init__(self,name,atm_total):
self.name = name
self.atm_total = atm_total
def add(self,money):
self.atm_total += money
print(f"机器{self.name}增加金额{money}元,{self.name}当前总金额为{self.atm_total}元")
def decrease(self,money):
if self.atm_total < money:
print(f"{self.name}余额不足,取钱失败")
else:
self.atm_total -= money
print(f"机器{self.name}取出金额{money}元,{self.name}当前总金额为{self.atm_total}元")
class Account():
def __init__(self,name,balance,passwd):
self.name = name
self.balance = balance
self.passwd = passwd
def draw(self,atm,money):
if money <= self.balance:
if money <= atm.atm_total:
self.balance -= money
atm.atm_total -= money
print(f"成功取款{money}元,{self.name}当前余额为{self.balance}元")
else:
print(f"ATM机 {atm.name}余额不足,取款失败!")
else:
print("您输入的金额大于您的账户余额,取款失败!")
def save(self,atm,money):
self.balance += money
atm.atm_total += money
print(f"成功存款{money}元,{self.name}当前余额为{self.balance}元")
def look(self):
print(f"{self.name}当前余额为{self.balance}元")
# 管理员操作
def atm_os():
# 管理员登录验证
name, paaswd = input("请输入管理员账号和密码,空格隔开\n").split()
if (name, paaswd) in admin_dict.items():
pass
else:
print("管理员账号出错")
return
while True:
print("请选择:1.创建ATM\t2.ATM加钱\t3.ATM取钱\t4.返回上一级")
enter_number = input("请输入你的选择\t")
if enter_number.isdigit():
enter_number = int(enter_number)
if 1 <= enter_number <= 4:
# 1、创建ATM
if enter_number == 1:
name, atm_total = input("请输入ATM名称,总金额,空格隔开\n").split()
atm_total = int(atm_total)
atm_dict[name] = Atm(name,atm_total)
print(f"创建ATM机 {name}成功,{name}当前总金额{atm_total}元")
# 2、ATM加钱
elif enter_number == 2:
print(f"当前存在的ATM机器:{atm_dict.keys()}")
atm_name = input("请输入ATM名称\n")
if atm_name in atm_dict.keys():
money = int(input("请输入金额\n"))
atm_dict[atm_name].add(money)
else:
print(f"{atm_name}不存在")
# 3、ATM取钱
elif enter_number == 3:
print(f"当前存在的ATM机器:{atm_dict.keys()}")
atm_name = input("请输入ATM名称\n")
if atm_name in atm_dict.keys():
money = int(input("请输入金额\n"))
if money > 0:
atm_dict[atm_name].decrease(money)
else:
print("取出的金额不能为负")
else:
print(f"{atm_name}不存在")
elif enter_number == 4:
print("退出ATM操作")
break
else:
print("输入错误,请输入1-4选择操作")
# 账户操作
def account_os():
while True:
print("请选择:1.创建账户\t2.取钱\t3.存钱\t4.查询余额\t5.返回上一级")
enter_number = input("请输入你的选择\t")
if enter_number.isdigit():
enter_number = int(enter_number)
if 1 <= enter_number <= 5:
# 1、创建账户
if enter_number == 1:
name, balance, passwd = input("请输入账户名称、余额和密码进行创建,空格分割\n").split()
balance = int(balance)
account_dict[name] = Account(name,balance,passwd)
account_passwd[name] = passwd
print(f"创建用户 {name}成功,余额为{balance}")
elif enter_number == 2 or enter_number == 3 or enter_number == 4:
print(f"当前的ATM机有{atm_dict.keys()}")
atm, name, passwd = input("请输入您选择的ATM机、您的账户名称和密码进行登陆,空格分割\n").split()
# 验证ATM是否存在
if atm in atm_dict.keys():
# 验证账户
if (name, passwd) in account_passwd.items():
atm = atm_dict[atm]
# 2、取钱
if enter_number == 2:
money = int(input("请输入取款金额\n"))
account_dict[name].draw(atm, money)
# 3、存钱
elif enter_number == 3:
money = int(input("请输入存款金额\n"))
account_dict[name].save(atm, money)
# 4、查询余额
elif enter_number == 4:
account_dict[name].look()
else:
print("账户错误")
else:
print(f"{atm}不存在")
elif enter_number == 5:
print("退出账户操作")
break
else:
print("输入错误,请输入1-5选择操作")
admin_dict = {"admin":"123456"} # 管理员信息
account_passwd = {} # 账户信息
atm_dict = {} # 存放初始化实例
account_dict = {} # 存放初始化实例
while True:
print("请选择:1.ATM操作\t2.账户操作\t3.退出")
enter_number = input("请输入你的选择\t")
if enter_number.isdigit():
enter_number = int(enter_number)
if 1 <= enter_number <= 3:
# 1、ATM操作
if enter_number == 1:
atm_os()
# 2、账户操作
elif enter_number == 2:
account_os()
else:
print("退出操作!")
exit()
else:
print("输入错误,请输入1-3选择操作")
else:
print("输入错误,请输入1-3选择操作")
示例2
#这种写法,把ATM和USER全放在一起不好。这里存在逻辑问题,没有过多的用户判断
# # 自定义密码异常
class PasswordException(Exception):
def __init__(self):
print("密码错误,请重试!")
# 自定义取款金额异常
class SumException(Exception):
def __init__(self):
print("余额不足,请重新输入取款金额")
class ATM:
# 定义一个标志器用于判断用户是否开过户
# 注:user、atm都变成了1个ATM类
flag = False # 注:设置1个标志化
account = ""
password = ""
sum1 = 0
def __init__(self,account,password,sum1):
self.account = account
self.password = password
self.sum1 = sum1
self.flag = True
print(f"开户成功!当前余额为:{self.sum1}")
# 存款
def deposit(self):
if self.flag == True:
while True:
try: # 注:密码异常,做异常捕获
account = input("请输入你的账户:")
password = input("请输入你的密码:")
if account == self.account:
if password == self.password:
amount_deposited = int(input("请输入存款金额:"))
self.sum1 += amount_deposited
print(f"你本次存入金额:{amount_deposited},当前余额为:{self.sum1}")
break
else:
raise PasswordException
except PasswordException as pe:
print("password error:",pe)
else:
print("请先开户!")
# 取款
def withdrawal(self):
if self.flag == True:
while True:
try:
account = input("请输入你的账户:")
password = input("请输入你的密码:")
if account == self.account:
if password == self.password:
while True:
try:
withdrawal_amount = int(input("请输入取款金额:"))
if withdrawal_amount > self.sum1:
# 注:如果取款金额大于ATM金额
raise SumException # 注:这里自定义了异常
else:
self.sum1 -= withdrawal_amount
print(f"你本次取出金额:{withdrawal_amount},当前余额为:{self.sum1}")
break
except SumException as se:
print("sum error:",se)
break
else:
raise PasswordException
except PasswordException as pe:
print("password error:",pe)
else:
print("请先开户!")
# 主界面
print("********** Welcome to ATM **********")
print("如果你未开户,请先进行开户操作!")
while True:
try:
print("1:开户\n2:存款\n3:取款\n4:退出")
option = input("请输入你的选择:")
if option.isdigit():
option = int(option)
if 1 <= option <= 4:
if option == 1:
user = input("请输入你的开户账号:")
secret = input("请输入你的初始密码:")
while True:
initial_amount = int(input("请输入你的初始金额:"))
if initial_amount > 10:
initial_amount -= 10
a = ATM(user,secret,initial_amount)
# 注:应该把实例化对象放到一个地方(推荐字典)
break
else:
print("初始金额应大于10元,请重新输入初始化金额!")
elif option == 2:
a.deposit()
elif option == 3:
a.withdrawal()
elif option == 4:
break
else:
print("请输入1-4的数字!")
except ValueError:
print("输入的值有误!")
练习5 Linux用户管理类
# Linux用户管理类
# ·基类:实现往linux系统里添加用户
# ·子类A:
# ·能够查看、修改uid和gid、shell等信息 ·子类C(A,B):
# ·子类B: ·1.可以单独新建组
# ·1.能删除用户 ·2.可以将某个用户的gid修改为新建的组的gid
# ·2.能删除组 ·3.加入异常机制,异常的名字需要自己定义
示例1
import subprocess
import os
class F():
def adduser(self,name):
subprocess.call('sudo useradd %s' %name,shell = True)
class A(F):
def catuser(self,name):
subprocess.call('sudo id %s'%name,shell = True)
def chuser(self):
print("#"*20)
print("1.修改用户uid")
print("2.修改用户gid")
print("3.修改用户shell")
print("4.exit")
print("#"*20)
while True:
name = input("请输入要修改的用户:")
a = input("请输入你的选择:")
if a=="1":
uid = input("请输入uid:")
subprocess.call(f'sudo usermod -u {uid} {name}',shell = True)
elif a=="2":
gid = input("请输入gid:")
subprocess.call(f"sudo usermod -g {gid} {name}",shell = True)
elif a=="4":
return
elif a=="3":
sh = input("请输入用户shell:")
subprocess.call(f"sudo usermod -s {sh} {name}",shell=True)
else :
print("请输入1-4")
class B(F):
def deluser(self,name):
subprocess.call(f"sudo userdel -r {name}",shell = True)
def delgrp(self,gname):
subprocess.call(f"sudo groupdel {gname}",shell = True)
class Except(Exception):
def __str__(self):
return "输入的username或gid不存在!"
class C(A,B):
def addgrp(self,gid,gname):
try:
if subprocess.call(f"sudo groupadd -g {gid} {gname}",shell=True)==1:
raise Except()
except Except as e:
print(e)
def chgrp(self,name):
gid=os.popen("awk -F ':' 'END {print$3}' /etc/group").readlines()
gid1 = "".join(gid).strip()
subprocess.call(f'sudo usermod -g {gid1} {name}',shell = True)
示例2
import subprocess
class Base():
def add(self,name,passwd):
subprocess.Popen(f'useradd {name} -p {passwd}&>/dev/null && echo "{name}创建成功" ||echo "创建失败"', shell=True)
class A(Base):
def look(self,name):
p = subprocess.Popen(f'cut -d ":" -f 1,3,4,7 /etc/passwd|grep -E ^{name}:', shell=True)
def modify(self,name,uid,gid,shell):
p = subprocess.Popen(f'usermod -u {uid} -g {gid} -s {shell} {name}&>/dev/null && echo "修改成功" ||echo "修改失败"', shell=True)
class B(Base):
def del_user(self,name):
p = subprocess.Popen(f'userdel -r {name}&>/dev/null && echo "删除成功" ||echo "创建失败"', shell=True)
def del_group(self,name):
p = subprocess.Popen(f'groupdel {name}&>/dev/null && echo "删除成功" ||echo "删除失败"', shell=True)
class C(A,B):
group_member = []
def group_add(self,gid,name):
p = subprocess.Popen(f'groupadd -g {gid} {name}&>/dev/null && echo "创建成功" ||echo "创建失败"', shell=True)
C.group_member.append(gid)
def gid_modify(self,gid,name):
if gid in C.group_member:
p = subprocess.Popen(f'usermod -g {gid} {name}&>/dev/null && echo "修改成功" ||echo "修改失败"', shell=True)
else:
print(f"修改失败,{gid}不是新建的组id")
class DefinedError(Exception):
def __str__(self):
return "这是自定义异常"
while True:
print('''请选择:
1.添加用户\t2.查看uid、gid和shell信息\t3.修改uid、gid和shell信息
4.删除用户\t5.删除组\t6.新建组\t7.修改用户gid\t8.触发异常\t9.退出''')
enter_number = input("请输入你的选择\t")
if enter_number.isdigit():
enter_number = int(enter_number)
if 1 <= enter_number <= 9:
if enter_number == 1:
sample = Base()
name, passwd = input("请输入用户名和密码,空格分割\n(2个参数)\t").split()
sample.add(name, passwd)
elif enter_number == 2:
sample = A()
name = input("请输入用户名\n")
sample.look(name)
elif enter_number == 3:
sample = A()
name,uid,gid,shell = input("请输入用户名,修改后的uid、gid和shell,空格分割\n(4个参数)\t").split()
sample.modify(name,uid,gid,shell)
elif enter_number == 4:
sample = B()
name = input("请输入用户名\n")
sample.del_user(name)
elif enter_number == 5:
sample = B()
name = input("请输入组名\n")
sample.del_group(name)
elif enter_number == 6:
sample = C()
name, gid = input("请输入组名、指定的gid,空格分割\n(2个参数)\t").split()
sample.group_add(gid,name)
elif enter_number == 7:
sample = C()
name, gid = input("请输入用户名、gid\n(2个参数)\t").split()
sample.gid_modify(gid,name)
elif enter_number == 8:
raise DefinedError
elif enter_number == 9:
print("退出系统")
exit()
else:
print("输入错误,请输入1-5选择操作!")
else:
print("输入错误,请输入1-5选择操作!")