话不多说,上代码,看结果。
print('2.3、方法相关##############################')
print('2.3.1、 方法的概念###################')
# 方法的概念
# 描述一个目标的行为动作 比如描述一个人怎样吃,怎样喝,怎样玩...
# 和函数非常类似
# 都封装了一系列行为动作
# 都可以被调用的之后,执行一系列行为动作
# 最主要的区别就是:调用方式
print('2.3.1、 方法的划分###################')
# 实例方法 默认第一个参数需要接收到一个实例
# 类方法 默认第一个参数需要接收到一个类
# 静态方法 静静的看着前面俩装逼,第一个参数啥也不默认接收
# 注意
# 1. 划分的依据是:方法的第一个参数必须要接收的数据类型
# 2. 不管是哪一种类型的方法,都是存储在类当中;没有在实例当中的
# 3. 不同类型方法的调用方式不同
# 但,不管怎么调,把握一个原则
# 不管是自己传递,还是解释器帮我们处理;最终要保证不同类型的方法第一个参数接收到的数据,是他们想要的类型
class A:
def shilifangfa(self):
print('实例方法')
@classmethod
def leifangfa(cls):
print('类方法')
@staticmethod
def jingtaifangfa():
print('静态方法')
a = A()
print(a)
# A.shilifangfa() # TypeError: shilifangfa() missing 1 required positional argument: 'self'
A.jingtaifangfa()
A.leifangfa()
print('2.4、类相关补充##############################')
print('2.4.1、元类#############################')
print('2.4.1.1、创建类对象的类#############################')
# 对象怎样产生的? 由类创建出来的 类是不是对象 是 所以,类对象是不是由另外一个类创建出来的? 是
print('2.4.1.2、类对象的创建方式以及创建流程#############################')
# 创建方式 通过class 定义 当我们这么写这个类描述的时候, 解释器会自动的帮我们创建对应的类对象
class B:
def C(self):
pass
d = B()
# 通过type函数进行创建
def D(self):
print(self)
x = type('E', (), {'123': 456, "789": 12})
print(x)
print(x.__dict__)
# 1. 检测类中是否有明确 __metaclass__属性 有, 则通过指定元类来创建这个类对象
# 2. 检测父类中是否存在__metaclass__属性 有, 则通过指定元类来创建这个类对象
# 3. 检测模块中是否存在__metaclass__属性 有, 则通过指定元类来创建这个类对象
# 4. 通过内置的type这个元类,来创建这个类对象
print('2.4.1.3、元类的应用场景#############################')
# 1)拦截类的创建
# 2)修改类
# 3)返回修改之后的类
print('2.4.2、 类的描述#############################')
# 目的 方便理清逻辑思路 方便多人合作开发时的沟通 方便生成项目文档...
# 描述方式
# 直接在类的下方,使用三个 "双引号"对就可以 需要注明类的作用, 以及类属性描述
# 至于方法, 则直接在方法下,使用三个"双引号"对描述即可 作用 参数 返回值
class Cal:
"""计算器"""
def jiafa(self, g, h):
"""
计算加法
:param g: 加数1,数值类型,无返回值
:param h: 加数2,数值类型,无返回值
:return: 数值类型, 返回加法的结果
"""
return g + h
j = Cal()
print(j.jiafa(1, 2))
# 生成项目文档(补充)
# 方式1
# 使用内置模块 pydoc
# 具体步骤
# 查看文档描述 python3 -m pydoc 模块名称
# 启动本地服务, 浏览文档 python3 -m pydoc -p 1234
# 生成指定模块html文档 python3 -m pydoc -w 模块名称
# 方式2
# 使用三方模块 Sphinx epydoc doxygen
# 具体步骤 和模块之后,会进行补充
print('2.5、属性相关补充##############################')
print('2.5.1、私有化属性##############################')
# 概念 是指将一些原本公开的属性设置权限, 只能小范围访问, 其他地方访问不了
# 意义 保证数据的安全性 提高代码的可维护性
# 注意 Python并没有真正的私有化支持,但是, 可以使用下划线完成伪私有的效果 类属性(方法)和实例属性(方法)遵循相同的规则
# x 公有属性 类内部访问 子类内部访问
# 模块内其他位置访问
# 类访问 父类 派生类
# 实例访问 父类实例 派生类实例
# 跨模块访问 import形式导入 from 模块 import * 形式导入
class G:
x = 0.123
def test(self):
print(G.x, self.x)
class H(G):
def test2(self):
print(G.x, self.x)
gg = G()
gg.test() # 类的内部访问
hh = H()
hh.test2() # 子类的内部访问
print(G.x, H.x, gg.x, hh.x) # 模块内其他位置访问,通过类、子类、类实例化对象、子类实例化对象访问
wo = '569'
# _y 受保护属性
# 类内部访问 子类内部访问
# 模块内其他位置访问
# 类访问 父类 派生类 警告
# 实例访问 父类实例 派生类实例 警告
# 跨模块访问
# import形式导入 警告
# from module import * 形式导入
# 有__all__指明对应变量
# 没有__all__指明对应变量 报错
class J:
_x = 'wo shi shui'
def test(self):
print(J._x, self._x)
class K(J):
def test2(self):
print(K._x, self._x)
jj = J()
jj.test() # 类的内部访问
kk = K()
kk.test2() # 子类的内部访问
print(J._x, K._x, jj._x, kk._x) # 模块内其他位置访问,通过类、子类、类实例化对象、子类实例化对象访问
__all__ = ['_a', 'wo', '__a']
_a = "qwe"
# __z
# 私有属性
# 类内部访问
# 子类内部访问 报错
# 模块内其他位置访问
# 类访问 父类 报错 派生类 报错
# 实例访问 父类实例 报错 派生类实例 报错
# 跨模块访问
# 参照单下划线开头变量的访问原则
class Q:
__x = '23333'
def test(self):
print(Q.__x, self.__x)
class W(Q):
def test2(self):
print(W.__x, self.__x)
qq = Q()
qq.test() # 类的内部访问
ww = W()
# ww.test2() # 子类的内部访问 报错 AttributeError: type object 'W' has no attribute '_W__x'
# print(Q.__x, W.__x, qq.__x, ww.__x) # 模块内其他位置访问,通过类、子类、类实例化对象、子类实例化对象访问
__a = "zxc"
# 私有属性的实现机制
# 名字重整(Name Mangling) 重改__x为另外一个名称, 如 _类名__x
# 目的 防止外界直接访问 防止被子类同名称属性覆盖
# 应用场景 数据保护 数据过滤
print(Q.__dict__) # '__module__': '__main__', '_Q__x': '23333', 。。。。。。
# print(Q.__x) # AttributeError: type object 'Q' has no attribute '__x'
print(Q._Q__x)
class Country:
def __init__(self):
self.__country = '齐国'
def setCountry(self, country):
self.__country = country
def getCountry(self):
return self.__country
c1 = Country()
c2 = Country()
c3 = Country()
# print(c1.__country) # AttributeError: 'Country' object has no attribute '__country'
# print(c1._Country__country) # 不建议这么用,要这样还设置私有化属性干啥
# c2.__country = '秦国'
# print(c2.__country) # 新建的实例属性,不是修改类属性!!!
# print(c2.__dict__) # {'_Country__country': '齐国', '__country': '秦国'}
c3.setCountry('燕国')
print(c3.getCountry())
print(c1.__dict__) # {'_Country__country': '齐国'}
print(c3.__dict__) # {'_Country__country': '燕国'}
# 补充
# xx_ "变量名_" 这个格式是为了与系统属性作区分
# __xx__ 一般为系统内置属性或方法, 所以以后命名注意避免
print('2.5.2、只读属性##############################')
# 概念 一个属性(一般指实例属性), 只能读取, 不能写入
# 应用场景 有些属性, 只限在内部根据不同场景进行修改, 而对外界来说, 不能修改, 只能读取
# 比如 电脑类的网速属性, 网络状态属性
# 方式1
# 方案
# 全部隐藏 私有化 既不能读 也不能写
# 部分公开 公开读的操作
# 具体实现 私有化 通过"属性前置双下划线"实现
# 部分公开 通过公开的方法
# 优化 property
# 作用
# 将一些"属性的操作方法"关联到某一个属性中
class Xiong:
def __init__(self):
self.animal1 = '熊大'
self.animal2 = '熊二'
def getanimal(self):
return self.__animal1
a1 = Xiong()
print(a1.getanimal)
class Xiong:
def __init__(self):
self.__animal1 = '熊大'
self.__animal2 = '熊二'
@property
def animal(self):
return self.__animal1
a1 = Xiong()
# a1.animal = '蹦蹦' # AttributeError: can't set attribute 只读属性,修改不了!!
print(a1.animal)
print(a1.__dict__)
# 概念补充
# 经典类 没有继承(object)
# 新式类 继承(object)
# Python2.x版本定义一个类时, 默认不继承(object)
# Python3.x版本定义一个类时, 默认继承(object)
# 建议使用 新式类
# property 在经典类中 只能管理一个属性的读取操作
# 在新式类中 可以管理一个属性的删改查操作
# class C(object):
# def getx(self): return self._x
# def setx(self, value): self._x = value
# def delx(self): del self._x
# x = property(getx, setx, delx, "I'm the 'x' property.")
class Xiong:
def __init__(self):
self._animal = '熊大'
self._animal2 = '熊二'
def getanimal(self):
return self._animal
def setanimal(self, value):
self._animal = value
def delanimal(self):
del self._animal2
animal = property(getanimal, setanimal, delanimal)
a1 = Xiong()
print(a1.animal)
a1.animal = "@@@虫大"
print(a1.animal)
# class C(object):
# @property
# def x(self):
# "I am the 'x' property."
# return self._x
# @x.setter
# def x(self, value):
# self._x = value
# @x.deleter
# def x(self):
# del self._x
class Forest:
def __init__(self):
self._animal = '熊大'
self._animal2 = '熊二'
@property
def animal(self):
return self._animal
@animal.setter
def animal(self, value):
self._animal = value
@animal.deleter
def animal(self):
del self._animal2
b1 = Forest()
print(b1.animal)
b1.animal = "虫大"
print(b1.animal)
# 方式2
# 方案 借助系统内置的方法进行拦截
# 具体实现 __setattr__方法
# 当我们使用 "实例.属性 = 值" 这种格式给一个实例增加或修改属性的时候, 都会调用系统内置的这个方法
# 在这个方法的内部, 才会真正的把属性以及对应的值给存储到 __dict__当中
# 解决方案 在这个方法中, 进行拦截
class senlin:
def __setattr__(self, key, value):
print('^^^', key, value)
if key == "animal" and key in self.__dict__.keys():
print("这个属性是只读属性, 不能设置数据")
else:
self.__dict__[key] = value
g1 = senlin()
print(g1.__dict__)
g1.animal2 = "虫二"
print(g1.__dict__)
g1.animal = "熊大"
print(g1.__dict__)
print('2.5.3、内置特殊属性##############################')
# 类属性
# __dict__ : 类的属性 __bases__ : 类的所有父类构成元组
# __doc__ :类的文档字符串 __name__: 类名 __module__: 类定义所在的模块
# 实例属性
# __dict__ : 实例的属性
# __class__: 实例对应的类
结果如下图
就先这样,遇到别的再补充。