面向对象
Posted tian-cai-1996
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象相关的知识,希望对你有一定的参考价值。
规范化目录
-
规范化目录的优点
#1:加载速度块
#2:可读性高
#3:查询修改代码时都简单
? -
规范化目录分析
-
划归固定的路径
将文件目录的固定路径划分完成
? -
settings.py配置文件
#1:基本存储的都是变量
#2:静态路径,数据库的链接,配置,静态文件的的路径,基本不发生改变的
? -
src.py主逻辑函数
#主逻辑函数,核心函数:贯穿整个项目的主要功能
? -
common.py公共组件
#放置一些公用的函数,功能,方便与其他的函数或者业务需求,如:装饰器
? -
start启动文件
#单独的启动文件,将所有项目的功能单独放置一个文件中,开启项目方便,醒目
? -
register
#用户信息,数据相关,多个文件
? -
logging日志文件
#记录用户的访问次数,转账,取钱,充钱等等.极了用户干了什么.
? -
README描述文件
#1:软件定位,软件的基本功能。
#2:运行代码的方法: 安装环境、启动命令等。
#3:简要的使用说明。
#4:代码目录结构说明,更详细点可以说明软件的基本原理。
#5:常见问题说明。
?
-
-
规范化目录sys模块路径加载
#版本一
sys模块内置模块,文件运行时,sys内置模块就会将一些模块 自动 加载到内存. 内置模块. time,json pickle等等.以及当前目录的.
如何引用到一个模块最本质的原因在于这个模块名称空间在不在内存.
如果直接引用不到一个模块,他必定不是内置或者当前目录下的py文件.
所以,我们要手动将其添加到内存.
sys.path.append()就是手动的将一些模块添加到内存,添加完毕之后,就可以直接引用了.
#================================================
import sys
#版本二: 繁琐,我要将整个项目作为根目录,添加到内存中.
sys.path.append(r‘F:s24day20模拟博客园代码logcore‘)
sys.path.append(r‘F:s24day20模拟博客园代码logconf‘)
sys.path.append(r‘F:s24day20模拟博客园代码logdb‘)
from src import run
run()
#================================================
#版本三: 你把项目路径写死了,所有的开发人员如果共同开发这个项目,必须都得按照这#个目录结构去构建.
import sys
sys.path.append(r‘F:s24day20模拟博客园代码log‘)
from core.src import run
run()
#================================================
# 版本四:
import sys
import os
?
# print(__file__)
# print(os.path.dirname(os.path.dirname(__file__)))
# sys.path.append(r‘F:s24day20模拟博客园代码log‘)
# from core.src import run
# run()
?
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_PATH)
from core.src import run
if __name__ == ‘__main__‘:
run()
目录结构:
blog
bin(starts),conf(settings),core(src),db,lib(common),log
面向对象编程的优势
#易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
?
面向对象初识
‘‘‘
想要学习面向对象必须站在一个上帝的角度去分析考虑问题.
类: 具有相同属性和功能的一类事物.
对象:某个类的具体体现.
?
汽车: 汽车类, 楼下停着一个车牌号为9nb11的奥迪对象.
猫科类: 类. 陈硕家的养的那个大橘.对象.
鸡类: 一个类. 家里养的一只鸡.
男神:是一类. 太白对象.
?
面向对象的第二优点: 你要站在上帝的角度构建代码,类就是一个公共的模板,对象就是从模板实例化出来的.
得到对象就得到了一切.
‘‘‘
?
面向对象的结构
class Human:
"""
类的具体结构
"""
# 第一部分:静态属性
mind = ‘有思想‘ # 类的属性 (静态属性, 静态字段)
language = ‘使用语言‘
?
# 第二部分: 动态方法
def work(self):
print(‘人类都会工作‘)
?
def eat(self):
print(‘人类都需要吃饭‘)
?
从类名的角度研究类
# class Human:
# """
# 类的具体结构
# """
# # 第一部分:静态属性
# mind = ‘有思想‘ # 类的属性 (静态属性, 静态字段)
# language = ‘使用语言‘
#
# # 第二部分: 动态方法
# def work(self):
# print(‘人类都会工作‘)
#
# def eat(self):
# print(‘人类都需要吃饭‘)
?
# 1. 类名操作类中的属性
# 1. 类名查看类中所有的内容
# print(Human.__dict__)
# 2. 类名操作类中的静态属性 万能的点.
?
# 增:
# Human.body = ‘有头和四肢‘
# 删:
# del Human.mind
# 改:
# Human.mind = ‘liye脑残‘
# 查:
# print(Human.language)
# print(Human.__dict__)
?
# 2. 类名调用类中的方法(一般类中的(静态方法,类方法)方法不会通过类名调用)
# Human.work(111)
?
# 总结:
# 一般类名就是操作类中的属性.
?
从对象角度研究类
# class Human:
# """
# 类的具体结构
# """
# # 第一部分:静态属性
# mind = ‘有思想‘ # 类的属性 (静态属性, 静态字段)
# language = ‘使用语言‘
#
# def __init__(self):
# # print(f‘self---->: {self}‘)
# # print(666)
# self.name = ‘李业‘
# self.age = 18
#
# # 第二部分: 动态方法
# def work(self):
# print(‘人类都会工作‘)
#
# def eat(self):
# print(‘人类都需要吃饭‘)
#
# obj = Human() # 实例化过程
# 得到一个返回值,这个返回值就是 对象,实例.
# print(f‘obj---> {obj}‘)
=================
# 实例化一个对象发生了三件事(重点++++):
‘‘‘
1. 触发__new__方法 ,开辟一个对象空间.
2. 自动执行__init__方法,并且将对象地址传给self.
3. 运行__init__方法内的代码,给对象空间封装属性.(完整版)
?
‘‘‘
?
?
?
class Human:
"""
类的具体结构
"""
# 第一部分:静态属性
mind = ‘有思想‘ # 类的属性 (静态属性, 静态字段)
language = ‘使用语言‘
?
def __init__(self, name, age):
# print(f‘self---->: {self}‘)
# print(666)
self.n = name
self.a = age
?
?
# 第二部分: 动态方法
def work(self):
# print(f‘self---> {self}‘)
print(f‘{self.n}都会工作‘)
?
?
def eat(self):
print(f‘{self.n}都需要吃饭‘)
?
# obj = Human(‘李业‘,18) # 实例化过程
# print(obj.n)
# print(obj.a)
# print(obj.__dict__)
?
# 一:对象操作对象空间的属性
?
# 1. 对象查看对象的空间的所有属性
# obj = Human(‘李业‘,18)
# print(obj.__dict__)
?
# 2. 对象操作对象空间的属性
# obj = Human(‘李业‘,18)
# 增:
# obj.sex = ‘laddy_boy‘
# 删:
# del obj.a
# 改:
# obj.a = 1000
# 查:
# print(obj.n)
# print(obj.__dict__)
?
# 二 对象查看类中的属性
# obj = Human(‘李业‘,18)
# # print(obj.mind)
# obj.mind = ‘无脑的‘
# print(obj.mind)
# print(Human.mind)
?
# 三 对象调用类中的方法
# obj = Human(‘孙戴维‘, 23)
# # print(f‘obj---> {obj}‘)
# obj.work()
# obj.eat()
?
# 一个类可以实例化多个对象
# obj1 = Human(‘李业‘,18)
# obj2 = Human(‘小可爱‘, 16)
# obj3 = Human(‘怼姐‘, 18)
?
# 变量,函数名:
# age_of_oldboy = 73
# Ageofoldboy
?
从空间角度研究类
对象空间与类空间有相同的名字, 对象. 肯定先从对象空间查找.
查询顺序:
• 对象.名字: 对象空间 类对象指针_--> 类空间 ---> 父类空间
• 类名.名字: 类空间 -----> 父类空间
?
类与类之间的关系
-
依赖关系
# 依赖关系: 将一个类的类名或者对象传入另一个类的方法中
?
# #1. 依赖关系: 主从之分.
# class Elephant:
# def __init__(self,name):
# self.name = name
# def open(self,obj):
# print(f‘{self.name} 默念三声: 3,2,1 开门‘)
# obj.be_open()
# def close(self):
# print(f‘{self.name} 默念三声: 3,2,1 关门‘)
#
# class Refrigerator:
# def __init__(self, name):
# self.name = name
# def be_open(self):
# print(f‘{self.name}冰箱 被打开了‘)
# def be_close(self):
# print(f‘{self.name}冰箱 被关闭了‘)
? -
组合关系
#给一个类的对象封装一个属性,此属性为另一个类的对象
#class Boy:
# def __init__(self,name,age,girlfriend=None):
# self.name=name
# self.age=age
# self.girlfriend=girlfriend
# def eat(self):
# if self.girlfriend:
# print(f‘{self.name}和{self.girlfriend.name}‘)
# else:
# print(‘吃个屁‘)
# class Girl:
# def __init__(self,name,age):
# self.name=name
# self.age=age
# p=Boy(‘李业‘,30)
# g=Girl(‘如花‘,56)
# p.girlfriend=g
# p.eat()
?
继承
-
初识继承
#字面意思: 儿子可以完全使用父亲的所有内容
#专业角度: 如果B类继承A类,
# B类就称为子类,派生类.
# A类就称为父类,基类,超类.
#面向对象三大特性之一:继承,封装,多态.
#继承: 单继承,多继承.
? -
继承的优点
#减少重复代码.
#增加类之间的耦合性.
#代码更加清晰,流畅.
? -
单继承
#类名执行父类属性方法
#对象执行父类属性方法
#在子类中既执行字类方法又执行父类方法
? -
多继承
#python 类分为两种:
#python2x :
#• python2.2之前,都是经典类.python2.2之后,经典类与新式类共存.
#python3x:
#• 全部都是新式类.
#经
典类: 不继承object类, 深度优先原则.
#新式类:继承object类. mro(C3)算法
#经典类的深度优先
#新式类的mro算法
===============================================
#如果想执行父类的func方法,这个方法并且子类中夜用,那么就在子类的方法中写上:
#1:父类.func(对象,其他参数)
#2:利用super,super().func(参数)
? -
super的用法(重点++++)
1:super 可以重构父类的方法
2:在新式类的多继承中,super严格按照 self 对象从属于类的mro顺序进行查找,默认执行本类 的下一个类(简单的记就是:跳过本类,按照Mro算法的执行顺序,执行下一类的操作)
? -
mro(C3)算法
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )(其中Child继承自Base1, Base2)
?如计算merge( [E,O], [C,E,F,O], [C] )
有三个列表 : ① ② ③
?
1 merge不为空,取出第一个列表列表①的表头E,进行判断
各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
2 取出列表②的表头C,进行判断
C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
3 进行下一次新的merge操作 ......
?mro(A) = mro( A(B,C) )
?
原式= [A] + merge( mro(B),mro(C),[B,C] )
?
mro(B) = mro( B(D,E) )
= [B] + merge( mro(D), mro(E), [D,E] ) # 多继承
= [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O]
= [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D
= [B,D,E] + merge([O] , [O])
= [B,D,E,O]
?
mro(C) = mro( C(E,F) )
= [C] + merge( mro(E), mro(F), [E,F] )
= [C] + merge( [E,O] , [F,O] , [E,F] )
= [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除
= [C,E,F] + merge([O] , [O])
= [C,E,F,O]
?
原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
= [A,B] + merge( [D,E,O], [C,E,F,O], [C])
= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E
= [A,B,D,C] + merge([E,O], [E,F,O])
= [A,B,D,C,E] + merge([O], [F,O]) # 跳过O
= [A,B,D,C,E,F] + merge([O], [O])
= [A,B,D,C,E,F,O]
? -
简述面向对象的新式类与经典类
#经典类
在python2.2之前. ?直使?的是经典类. 经典类在基类的根如果什么都不写.经典类采用深度优先遍历方案
#新式类
在python2.2之后出现了新式类. 新式类的特点是基类的根是object类,python3中使?的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object,新式类采用C3算法遍历原则,MRO序列
?
面向对象的三大特性
-
封装
#对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容
把很多数据封装到?个对象中. 把固定功能的代码封装到?个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了?个很?B的函数. 那这个也可以被称为封装. 在?向对象思想中. 是把?些看似?关紧要的内容组合到?起统?进?存储和使?. 这就是封装.
? -
继承
#?类可以?动拥有?类中除了私有属性外的其他所有内容. 说?了, ??可以随便?爹的东?. 但是朋友们, ?定要认清楚?个事情. 必须先有爹, 后有??. 顺序不能乱, 在python中实现继承非常简单. 在声明类的时候, 在类名后?添加?个?括号,就可以完成继承关系. 那么什么情况可以使?继承呢? 单纯的从代码层?上来看. 两个类具有相同的功能或者特征的时候. 可以采?继承的形式. 提取?个?类, 这个?类中编写着两个类相同的部分. 然后两个类分别取继承这个类就可以了. 这样写的好处是我们可以避免写很多重复的功能和代码. 如果从语义中去分析的话. 会简单很多. 如果语境中出现了x是?种y. 这时, y是?种泛化的概念. x比y更加具体. 那这时x就是y的?类. 比如. 猫是?种动物. 猫继承动物. 动物能动. 猫也能动. 这时猫在创建的时候就有了动物的"动"这个属性. 再比如, ?骨精是?个妖怪. 妖怪天?就有?个比较不好的功能叫"吃?", ?骨精?出?就知道如何"吃?". 此时 ?骨精继承妖精.
? -
多态
#多态,同一个对象,多种形态。python默认支持多态。
? -
三大特性总结
#继承:单继承和多继承,子承父业
如果B继承A,那A称作父类,基类,B称作子类,派生类
B继承A,那么B就可以拥有A所有的属性和方法,一个类可以多个父类
?
#多态
多种形态,Python中有很多地方都体现了多态,例如:定义一个变量a,a=2,这时a是个整型
我也可以再给a赋值,a = ‘你好‘,这时的a就是一个字符串类型,一个变量有多种形态,体现的就是多态
?
#封装
python中的函数 模块 类 都属于封装,把固定功能的代码封装到一个代码块中,就属于封装
?
类的约束
-
约束的概念
#约束. 其实就是?类对?类进?约束. ?类必须要写xxx?法. 在python中约束的?式和?法有两种:
#1. 使?抽象类和抽象?法, 由于该?案来源是java和c#. 所以使?频率还是很少的
#2. 使??为抛出异常的?案. 并且尽量抛出的是NotImplementError. 这样比较专业, ?且错误比较明确.(推荐)
? -
约束的两种方式
#第一种
class Payment:
"""
此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
"""
def pay(self,money):
raise Exception("你没有实现pay方法")
?
class QQpay(Payment):
def pay(self,money):
print(‘使用qq支付%s元‘ % money)
?
class Alipay(Payment):
def pay(self,money):
print(‘使用阿里支付%s元‘ % money)
?
class Wechatpay(Payment):
def fuqian(self,money):
print(‘使用微信支付%s元‘ % money)
?
?
def pay(obj,money):
obj.pay(money)
?
a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)
#========================================================
#第二种
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类
super()的深入了解
#严格按照mro的执行顺序去执行
#super(Foo,self).f2() # 按照self对象从属于类的mro的顺序,执行Foo类的下一个类.
?
class A:
def f1(self):
print(‘in A‘)
?
class Foo(A):
def f1(self):
super().f1()
print(‘in Foo‘)
?
class Bar(A):
def f1(self):
print(‘in Bar‘)
?
class Info(Foo,Bar):
def f1(self):
super().f1()
print(‘in Info f1‘)
?
obj = Info()
obj.f1()
?
‘‘‘
in Bar
in Foo
in Info f1
‘‘‘
print(Info.mro()) # [<class ‘__main__.Info‘>, <class ‘__main__.Foo‘>, <class ‘__main__.Bar‘>, <class ‘__main__.A‘>, <class ‘object‘>]
?
鸭子类型
-
什么是鸭子类型
#对相同的功能定义了相同的名字,这样方便开发,两种方法互称为鸭子模型,比如:list str tuple 都有index方法,这种就是统一了规范,互为鸭子模型.
?
#python中有一句谚语说的好,你看起来像鸭子,那么你就是鸭子。
#对于代码上的解释其实很简答:
class A:
def f1(self):
print(‘in A f1‘)
def f2(self):
print(‘in A f2‘)
?
class B:
def f1(self):
print(‘in A f1‘)
def f2(self):
print(‘in A f2‘)
obj = A()
obj.f1()
obj.f2()
?
obj2 = B()
obj2.f1()
obj2.f2()
# A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
# 对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。
?
# 这样的例子比比皆是:str tuple list 都有 index方法,这就是统一了规范。
# str bytes 等等 这就是互称为鸭子类型。
?
类的私有成员
-
类的私有属性
#类的私有属性,只能在类的内部使用,不能在类的外部和派生类中使用
class A:
name=‘李业‘
__name=‘李业‘
def func(self):
print(self.name)
print(self.__name)
class B(A):
def func(self):
print(self.name)
print(self.__name)
p=A()
p.func()
b=B()
b.func()#报错
? -
私有对象属性
#私有对象属性,只能在类的内部使用,不能在类的外部或派生类中使用
class A:
def __init__(self,name,age):
self.name=name
self.__age=age
def func(self):
print(self.__age)
class B(A):
def func():
print(self.__age)
p=A()
p.func()
b=B()
b.func()#报错
? -
类的私有方法
#类的私有方法只能在类的内部使用,不能在类的外部或者派生类中使用
class A:
def __init__(self,name,age):
self.name=name
self.__age=age
def __func(self):
print(self.__age)
def func(self):
self.__func()
class B(A):
def func():
self.__func()
print(self.__age)
p=A()
p.func()
b=B()
b.func()#报错
? -
类的私有成员总结
#私有成员来说: 当你遇到重要的数据,功能,(只允许本类使用的一些方法,数据)设置成私有成员.
# python所有的私有成员都是纸老虎,形同虚设.
?
class A:
name = ‘李业‘
__name = ‘钢哥‘ # 私有类的属性
?
def __func(self):
print(‘in __func‘)
?
print(A.__dict__)
print(A._A__name)
# 类从加载时,只要遇到类中的私有成员,都会在私有成员前面加上_类名
? -
类方法
# 类方法
class A:
def func(self):
print(‘实例方法‘)
?
-
静态方法
# 静态方法
# class A:
#
# def func(self):
# print(‘实例方法‘)
#
#
# @classmethod
# def cls_func(cls):
# pass
#
# @staticmethod
# def static_func():
# print(‘静态方法‘)
#
# # 静态方法是不依赖于对象与类的,其实静态方法就是函数.
# 保证代码的规范性,合理的划分.后续维护性高.
# def func():
# pass
?
?
import time
?
class TimeTest(object):
?
area = ‘中国‘
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
?
def change_time(self):
print(f‘你想调整的时间: {self.hour}时{self.minute}分{self.second}秒‘)
?
-
属性方法
# class Bmi:
#
# def __init__(self,name,height,weight):
#
# self.name = name
# self.height = height
# self.weight = weight
#
# def bmi(self):
# return self.weight/self.height**2
#
# obj = Bmi(‘赵嘎‘, 1.83, 65)
# print(obj.bmi())
# 结果虽然实现了,但是逻辑上感觉不合理.bmi应该是类似于name,age,height,等名词,
# 但是你把它当做方法使用了.
?
?
# class Bmi:
#
# def __init__(self,name,height,weight):
#
# self.name = name
# self.height = height
# self.weight = weight
#
# @property
# def bmi(self):
# return self.weight/self.height**2
#
# obj = Bmi(‘赵嘎‘, 1.83, 65)
# print(obj.bmi)
# property 将执行一个函数需要函数名()变换成直接函数名.
# 将动态方法 伪装 成了一个属性,虽然在代码级别上没有什么提升,但是让你看起来更合理.
# obj.bmi
# obj.bmi
# obj.bmi = 666
#
# del obj.bmi
?
# property 他是一个组合.
?
# class Foo:
# @property
# def bmi(self):
# print(‘get的时候运行我啊‘)
#
# @bmi.setter
# def bmi(self,value):
# print(value)
# print(‘set的时候运行我啊‘)
# # return 111 # 无法得到返回值
#
# @bmi.deleter
# def bmi(self):
# print(‘delete的时候运行我啊‘)
# # return 111 # 无法得到返回值
#
# obj = Foo()
# # obj.bmi
# obj.bmi = 666 # 操作命令 这个命令并不是改变bmi的值,而是执行被bmi.setter装饰器装饰的函数
# # obj.bmi(666)
# del obj.bmi
# 应用场景:
# 1, 面试会考一些基本的调用,流程.
# 2, 工作中如果遇到了一些类似于属性的方法名,可以让其伪装成属性.
?
?
# 设置属性的两种方式:
# 1, 利用装饰器设置属性.
# class Foo:
# @property
# def bmi(self):
# print(‘get的时候运行我啊‘)
#
# @bmi.setter
# def bmi(self,value):
# print(value)
# print(‘set的时候运行我啊‘)
# # return 111 # 无法得到返回值
#
# @bmi.deleter
# def bmi(self):
# print(‘delete的时候运行我啊‘)
# # return 111 # 无法得到返回值
?
# 2. 利用实例化对象的方式设置属性.
?
# class Foo:
# def get_AAA(self):
# print(‘get的时候运行我啊‘)
#
# def set_AAA(self,value):
# print(‘set的时候运行我啊‘)
#
# def delete_AAA(self):
# print(‘delete的时候运行我啊‘)
#
# AAA = property(get_AAA,set_AA,delete_AAA) #内置property三个参数与get,set,delete一一对应
?
# f1=Foo()
# f1.AAA
# f1.AAA=‘aaa‘
# del f1.AAA
? -
内置函数isinstance和issubclass
# isinstance 判断的是对象与类的关系
class A:
pass
?
class B(A):
pass
?
obj = B()
# isinstance(a,b) 判断的是 a是否是b类 或者 b类派生类 实例化的对象.
# print(isinstance(obj, B)) # True
# print(isinstance(obj, A)) # True
?
# issubclass 类与类之间的关系
class A:
pass
?
class B(A):
pass
?
class C(B):
pass
# issubclass(a,b) 判断的是 a类是否是b类 或者 b类派生类 的派生类.
# issubclass(a,b) 判断的是 a类是否是b类 子孙类.
# print(issubclass(B,A))
# print(issubclass(C,A))
?
Python中如何判断一个对象是否可调用?如果定义一个类,使其对象本身变成可调用对象
# 第一种方法callable,返回True有可能调用失败,但是返回False,那绝对不能调用
def func():
print(1)
func()
print(callable(func))
# 第二种方法,判断对象类型是否属于FunctionType,若为True,则可调用
from types import FunctionType
print(isinstance(func,FunctionType))
# 第三种方法,判断对象是否实现__call__方法
print(hasattr(func,‘__call__‘))
# 静态方法属于函数,类方法和实例方法分别依赖于类和对象,所以他们是method,其余我们自己定义的都是函数,函数就可调用若想让一个类的实例化对象可调用,可在类中定义__call__方法,即可实现
?
元类
#python中一切皆对象,类在某种意义上也是一个对象,python中自己定义的类,以及大部分的内置类,都是由type元类(构建类)实例化来的
===================================================
#type与object的关系
object是type类的一个实例 print(type(object))
object是type类的父类 print(issubclass(type,object))
#class A:
# pass
# obj = A()
# print(type(‘abc‘))
# print(type([1,2,3]))
# print(type((22,33)))
# # type 获取对象从属于的类
# print(type(A))
# print(type(str))
# print(type(dict))
?
-
说说type元类与object类的区别与联系
type元类是获取该对象从属于的类,而type类比较特殊,Python原则是:一切皆对象,其实类也可以理解为‘对象‘,
而type元类又称作构建类,python中大多数内置的类(包括object)以及自己定义的类,都是由type元类创造实例化得来的。
* 而type类与object类之间的关系比较独特:object是type类的实例,而type类是object类的子类,这种关系比较神奇无法使用python的代码表述,因为定义其中一个之前另一个必须存在.
?
反射
-
反射的概念
#反射是程序对自己内部代码的一种自省方式
#反射是通过字符串去操作对象的方式
? -
反射的主要作用
#反射主要作用与:
# 1:实例对象
# 2:类
# 3:其他模块
# 4:本模块
=====================================
#反射的组合:
# hasattr,getattr,setattr,delattr
? -
代码演示
# 实例对象:
?
class A:
country = ‘中国‘
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(‘in A func‘)
obj = A(‘赵海狗‘,47)
# hasattr
print(hasattr(obj,‘name‘))
print(hasattr(obj,‘country‘))
print(hasattr(obj,‘func‘))
?
print(getattr(obj,‘name‘))
print(getattr(obj,‘func‘))
f = getattr(obj,‘func‘)
f()
print(getattr(obj,‘sex‘,None))
if hasattr(obj,‘name‘):
getattr(obj,‘name‘)
?
# setattr,delattr 用的很少
obj.sex = ‘公‘
print(obj.sex)
setattr(obj,‘sex‘,‘公‘)
print(obj.__dict__)
delattr(obj,‘name‘)
print(obj.__dict__)
# 从类的角度:
?
class A:
country = ‘中国‘
def __init__(self,name,age):
self.name = name
self.age = age
?
def func(self):
print(self)
print(‘in A func‘)
if hasattr(A,‘country‘):
print(getattr(A,‘country‘))
if hasattr(A,‘func‘):
obj = A(‘赵海狗‘, 26)
getattr(obj,‘func‘)()
getattr(A,‘func‘)(obj)
# 从其他模块:
import tbjx
print(getattr(tbjx,‘name‘))
getattr(tbjx,‘func‘)()
import tbjx
# 1. 找到tbjx对象 的C类,实例化一个对象.
print(getattr(tbjx,‘C‘))
obj = getattr(tbjx,‘C‘)(‘123‘)
# 2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area.
print(getattr(tbjx.C,‘area‘))
# 3. 找到tbjx对象 的C类,实例化一个对象,对对象进行反射取值.
obj = getattr(tbjx,‘C‘)(‘赵海狗‘)
print(obj.name)
print(getattr(obj,‘name‘))
#从当前模块研究反射:
a = 666
def func1():
print(‘in 本模块这个对象‘)