面向对象
特殊成员
class Foo(object):
def __init__(self,a1,a2):
self.a1 = a1
self.a2 = a2
def __call__(self, *args, **kwargs):
print(11111,args,kwargs)
return 123
def __getitem__(self, item):
print(item)
return 8
def __setitem__(self, key, value):
print(key,value,111111111)
def __delitem__(self, key):
print(key)
def __add__(self, other): 对象相加
return self.a1 + other.a2
def __enter__(self): 和下面exit成对出现
print('1111')
return 999
def __exit__(self, exc_type, exc_val, exc_tb):
print('22222')
# 1. 类名() 自动执行 __init__
# obj = Foo(1,2)
# 2. 对象() 自动执行 __call__
# ret = obj(6,4,2,k1=456)
# 3. 对象['xx'] 自动执行 __getitem__
# ret = obj['yu']
# print(ret)
# 4. 对象['xx'] = 11 自动执行 __setitem__
# obj['k1'] = 123
# 5. del 对象[xx] 自动执行 __delitem__
# del obj['uuu']
# 6. 对象+对象 自动执行 __add__
# obj1 = Foo(1,2)
# obj2 = Foo(88,99)
# ret = obj2 + obj1
# print(ret)
# 7. with 对象 自动执行 __enter__ / __exit__
# obj = Foo(1,2)
# with obj as f:
# print(f)
# print('内部代码')
# 8. 真正的构造方法
# class Foo(object):
# def __init__(self, a1, a2): # 初始化方法
# """
# 为空对象进行数据初始化
# :param a1:
# :param a2:
# """
# self.a1 = a1
# self.a2 = a2
#
# def __new__(cls, *args, **kwargs): # 构造方法
# """
# 创建一个空对象
# :param args:
# :param kwargs:
# :return:
# """
# return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.).
#
# obj1 = Foo(1,2)
# print(obj1)
#
# obj2 = Foo(11,12)
# print(obj2)
day25
特殊方法补充
# __str__
class F1(object):
def __init__(self):
pass
def func(self):
pass
# 当加了__str__,返回的不再是对象的内存地址,而是str中返回的内容
def __str__(self):
return 'F1类'
obj = F1()
print(obj) # <__main__.F1 object at 0x0000018D3F823470> ,返回内存地址
print(obj) # F1类 ,当添加了str方法就打印的是返回值
# __doc__
class F1(object):
'''
这里是F1类
'''
def __init__(self):
pass
def func(self):
pass
obj = F1()
print(obj.__doc__) # 打印类最前面的注释,将注释放在下面就打印为None
# __dict__
class F1(object):
'''
这里是F1类
'''
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
pass
obj = F1('aaa',23)
print(obj.__dict__) # {'name': 'aaa', 'age': 23},获取的是一个字典,这样就能获取到对象中的变量值
# __iter__
# 列表也是一个类,可以for循环,但们自己写的类就无法循环,也叫不可迭代,添加如下方法可变迭代,使用for循环
'''
class F1(object):
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
pass
obj = F1('aaa',23)
for item in obj: # 报错
print(item)
'''
# 让类变可迭代方法如下
# 1.在类中定义__iter__方法
# 2.在iter中返回一个迭代器,或者一个生成器,生成器也是特殊的迭代器
# 第一种方法,返回迭代器iter()
'''
class F1(object):
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
pass
def __iter__(self):
return iter([11,22,33])
obj = F1('aaa',23)
for item in obj:
print(item)
# 11
# 22
# 33
'''
# 第二种方法,返回生成器
'''
class F1(object):
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
pass
def __iter__(self):
yield 11
yield 22
yield 33
obj = F1('aaa',23)
for item in obj:
print(item)
# 11
# 22
# 33
'''
类变量的练习题,列表
# 第三题:
"""
class StarkConfig(object):
list_display = []
def get_list_display(self):
self.list_display.insert(0,33)
return self.list_display
class RoleConfig(StarkConfig):
list_display = [11,22]
s1 = StarkConfig()
s2 = RoleConfig()
result1 = s1.get_list_display()
print(result1) # 33
result2 = s2.get_list_display()
print(result2) # 33,11,22
"""
# 第四题:
"""
class StarkConfig(object):
list_display = []
def get_list_display(self):
self.list_display.insert(0,33)
return self.list_display
class RoleConfig(StarkConfig):
list_display = [11,22]
s1 = RoleConfig()
s2 = RoleConfig()
result1 = s1.get_list_display()
print(result1) # 33,11,22
result2 = s2.get_list_display()
print(result2) # 33,33,11,22
"""
issubclass, type, isinstance
# issubclass
class Foo(object):
pass
class Bar(Foo):
pass
print(issubclass(Foo,Bar)) # 第一个参数是子类,第二个是父类
# False
print(issubclass(Bar,Foo))
# True
# type 判断对象是不是由某一个指定类?
obj = Foo()
print(type(obj)) # <class '__main__.Foo'>
if type(obj) == Foo:
print('obj是Foo的对象') # obj是Foo的对象
# 当将一堆对象传给一个函数时,如何判断一个对象是那个类的
def func(*args):
foo_count = 0
bar_count = 0
for item in args:
if type(item) == Foo:
foo_count += 1
elif type(item) == Bar:
bar_count += 1
return foo_count,bar_count
s1,s2 = func(Foo(),Bar(),Foo())
print(s1,s2) # 2 1
# isinstance 检查第一个参数(对象)是否是第二个参数(类及父类)的实例
class Foo(object):
pass
class Bar(Foo):
pass
class Base(Bar):
pass
obj = Base()
print(isinstance(obj,Foo)) # True # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例
print(isinstance(obj,Bar)) # True
print(isinstance(obj,Base)) # True
obj1 = Bar()
print(isinstance(obj1,Foo)) # True
print(isinstance(obj1,Bar)) # True
print(isinstance(obj1,Base)) # False
"""
给你一个参数,判断对象是不是由某一个指定类? type --> type(obj) == Foo
给你一个参数,判断对象是不是由某一个指定类或其父类? isinstance --> instance(obj,Foo)
"""
方法和函数(不重要)
称谓:
类,方法
外,函数
到底方法函数?
对象.xxx --> xxx就是方法
类.xxx --> xxx就是函数
xxx --> xxx就是函数
打印查看:
function
method
代码检查:
from types import MethodType,FunctionType
def check(arg):
"""
检查arg是方法还是函数?
:param arg:
:return:
"""
if isinstance(arg,MethodType):
print('arg是一个方法')
elif isinstance(arg,FunctionType):
print('arg是一个函数')
else:
print('不知道是什么')
反射
总结:
v = getattr(obj,"func") # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员。
好记:
getattr # 根据字符串的形式,去对象中找成员。
hasattr # 根据字符串的形式,去判断对象中是否有成员。
setattr # 根据字符串的形式,动态的设置一个成员(内存)
delattr # 根据字符串的形式,动态的删除一个成员(内存)
具体实例见day25
问题:你见过那些加()
类(),函数(),方法(),对象()是执行__call__方法
可以通过callable(方法/类,函数,对象)判断
Day 26
约束 ***
class BaseMessage(object):
def send(self):
"""
必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑。
"""
raise NotImplementedError(".send() 必须被重写.")
# raise Exception(".send() 必须被重写.")
BaseMessage类用于约束,约束其派生类:保证派生类中必须编写send方法,不然执行可能就会报错。
总结:
1. 什么是接口以及作用?
接口时一种数据类型,主要用于约束派生类中必须实现指定的方法。
Python中不存在,Java和C# 中是存在的。
2. Python中使用过什么来约束呢?
- 抽象类+抽象方法,编写上麻烦。
- 人为主动抛出异常
3. 约束时,抛出的异常是否可以用其他的?
不专业:raise Exception(".send() 必须被重写.")
专业:raise NotImplementedError(".send() 必须被重写."
4. 以后看代码,揣摩心思
5. 写代码:
class BaseMessage(object):
def send(self,x1):
"""
必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑。
"""
raise NotImplementedError(".send() 必须被重写.")
class Email(BaseMessage):
def send(self,x1):
"""
必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑。
"""
print('发送邮件')
obj = Email()
obj.send(1)
6. 应用场景:
多个类,内部都必须有某些方法时,需要使用基类+异常进行约束。
自定义异常类 ***
# 通过自定义异常类,捕获到异常,返回自己想要的信息
# 知识点:如何自定义异常类
class MyException(Exception):
def __init__(self,code,msg):
self.code = code
self.msg = msg
try:
# 代码块
raise MyException(1000,'操作异常')
except KeyError as obj:
print(obj,111)
except MyException as obj: # 捕获异常
print(obj,222)
except Exception as obj: # 当发生了自己没有预料到的异常
print(obj,333)
加密 hashlib *****
# 示例二
# 当用通用的md5加密时,可能能在网上破解,因此可以在实例化的时候加盐,达到算出不一样的md5加密
obj1 = hashlib.md5(b'd4df')
obj1.update('admin'.encode('utf-8'))
# 获取密文
print(obj1.hexdigest()) # ef8470e742484678a6307585a209e5fa
# 示例三
# 当在实际使用中,用户输入用户名,保存在数据库中,此时的数据必须加密,当在
# 验证时,可以将用户输入的密码加密,和数据库中的密文进行对比,
def md5(pwd):
obj3 = hashlib.md5(b'd4df')
obj3.update('admin'.encode('utf-8'))
return obj3.hexdigest()
user = input('请输入用户名:')
pwd = input('请输入密码:')
if user == 'admin' and md5(pwd) == 'ef8470e742484678a6307585a209e5fa':
print('登录成功')
日志logging ****
import logging
logger = logging.basicConfig(filename='log.txt',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=30)
logging.debug('level-10')
logging.info('level-20')
logging.warning('level-30')
logging.error('level-40')
logging.critical('level-50')
# 以上是日志对应的级别,config里面为对应的日志内容,可以直接copy
import traceback
def func():
try:
a = a +1
except Exception as e:
# 获取当前错误信息的堆栈信息
logging.error(traceback.format_exc())
func()
多日志文件
import logging
# 创建一个操作日志的对象logger(依赖FileHandler)
file_handler = logging.FileHandler('1.log','a',encoding='utf-8')
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
logger1 = logging.Logger('s1',level=logging.ERROR)
logger1.addHandler(file_handler)
logger1.error('将错误信息写入1.log文件中')
# 再创建一个操作日志的对象logger(依赖FileHandler)
file_handler1 = logging.FileHandler('2.log','a',encoding='utf-8')
file_handler1.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
logger2 = logging.Logger('s2',level=logging.ERROR)
logger2.addHandler(file_handler1)
logger2.error('将错误信息写入2.log文件中')
argparse模块
argsparse是python的命令行解析的标准模块
# ##分析传入参数
parser = ArgumentParser(description='manual to this script')
parser.add_argument('--case', type=str, default='')
parser.add_argument('--service', type=str, default='')
args = parser.parse_args()
Cmd下
python main.py --case projects.service.verifyservice
打印args结果为
Namespace(case='projects.service.verifyservice', service='')
可选参数
为了在命令行中避免上述位置参数的bug(容易忘了顺序),可以使用可选参数,这个有点像关键词传参,但是需要在关键词前面加(以上实例就是可选参数,如果去掉—就是位置参数需要一一对应)
默认值
add_argument中有一个default参数。有的时候需要对某个参数设置默认值,即如果命令行中没有传入该参数的值,程序使用默认值。如果命令行传入该参数,则程序使用传入的值
必需参数
add_argument有一个required参数可以设置该参数是否必需。required=True
parser.add_argument('--name', type=str, required=True, default='', help='名')
configparser模块简介
以下是 configparser 模块的基本方法:
- 读取配置文件
- defaults() 返回包含实例范围默认值的字典
- read(filename) 直接读取ini文件内容
- sections() 获取所有的 section,以列表的形式返回
- options(section) 获取指定 section 的所有的 option
- items(section) 获取指定 section 所有的键值对
- get(section, option) 获取指定 section 中 option 的值
- getint(section, option) 获取指定 section 中 option 的值,以 int 类型返回
- getfloat(section, option) 获取指定 section 中 option 的值,以 float 类型返回
- getboolean(section, option) 获取指定section 中 option 的值,以 boolean类型返回
- 写入配置文件
- add_section(section) 添加指定的新的 section
- has_section(section) 判断是否存在指定的 section
- set(section, option, value) 设置指定 section 中 option 的值
- remove_section(section) 删除指定 section
- remove_option(section, option) 删除指定 section 中的 option
- write(fileobject) 将内容写入配置文件
https://blog.csdn.net/atlansi/article/details/83243478
importlib模块
Python中动态导入对象importlib.import_module()的使用
一个函数运行需要根据不同项目的配置,动态导入对应的配置文件运行。
from importlib import import_module
or
import importlib
im = importlib.import_module()