1,封装
封装:
就是把属性和方法装起来
广义:就是把属性和方法装起来外面不能直接调用了,要通过类的名字来调用
狭义:就是把属性和方法藏起来外面不能调用,只能在内部调用
私有化:所有的私有化都是为了让用户不在外部调用类中的某个名字 如果完全私有化 那么这个类的封装度就更高了 封装度越高各种属性和方法的安全性也更高 但是代码越复杂。 使用私有类的三种方情况: 1、不能看也不能改 2、可以看不能改 3、可以看也可以改 但是要按照我的要求改 封装的语句: 1、私有的静态变量 2、私有的实例变量 3,、私有的绑定方法 私有的特点: 1、能不能在类的内部使用? 2、能不能在类的外部使用? 3、能不能在类的子类中使用? 原理: 1、如何变形? 2、在哪里定义的时候变形? 类中变量的级别,哪些是python支持的,哪些是python不支持的: 1、公有的 2、保护的 3、私有的
广义例子
class A:
a = 1
b = 2
print(A.b) # 通过类名封装,广义封装
狭义封装(私有化)
class User:
def __init__(self, name, password):
self.user = name
self.__pwd = password # 给一个名字前面加上一双下划线的时候,这个名字就变成了一个私有的
def pwd(self): # 通过对象名调用该方法可以查看私有的属性 ,用户只能看不能改
return self.__pwd
def change_pwd(self):pass # 表示用户必须用我们自定义的修改方式来进行变量的修改 私有+change()方法实现
alex = User('alex','123456')
# print(alex.__pwd) # 报错
print(alex.pwd()) # 123456
给一个变量名字前面加上了下划线的时候,这个名字就变成了一个私有的 所有的私有的内容或则名字都不能在类的外部调用,只能在类的内部使用
例;
class User:
__Country = 'China' # 私有的静态变量
def func(self): # 在类的内部可以调用
return self.__Country
print(User.Country) # 报错 在类的外部不能调用
print(User.__Country) # 报错
user = User()
print(user.func())
# 方法私有化
import hashlib
class User:
def __init__(self, name, pwd):
self.user = name
self.__pwd = pwd # 私有的实例变量
def __get_md5(self): # 私有的方法
md5 = hashlib.md5(self.user.encode('utf-8'))
md5.update(self.__pwd.encode('utf-8'))
return md5.hexdigest()
def getpwd(self):
return self.__get_md5()
alex = User('alex', '123456')
print(alex.getpwd())
# 94e4ccf5e2749b0bfe0428603738c0f9
# 526996078c7a54cf8bbc10a17cf11844
边缘知识
1、加了下划线的名字为什么不能从类的外部调用? 2、私有的内容能不能被子类使用? 3、在其他语言中的数据的级别都由哪些?在python中有哪些?
# 1、加了下划线的名字为什么不能从类的外部调用?
class User:
__Country = 'China' # 私有的静态变量
def func(self):
print(self.__Country) # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形
def country(self):
return self.__Country
print(User.__dict__)
print(User().country()) # 正常情况的找
print(User._User__Country) # 硬找
# # 只是把 '__Country' ----> '_User__Country'
# User.__aaa = 'bbb' # 在外部根本不能定义私有的概念
# 2、私有的内容能不能被子类继承使用? 不能。
class Foo(object):
def __init__(self):
self.func()
def func(self):
print('in Foo')
class Son(Foo):
def func(self):
print('in Son')
Son() # in Son 结果分析见图封装-边缘知识-2(01).png
#
#
class Foo(object):
def __init__(self):
self.__func()
def __func(self):
print('in Foo')
class Son(Foo):
def __func(self):
print('in Son')
Son() # in Foo 结果分析见图封装-边缘知识-2(02).png
# 3、在其他语言中的数据的级别都由哪些?在python中有哪些?
'''
public 公有的 类内类外都能使用,父类子类都能用 python支持
protect 保护的 类内使用,父类子类都能用,类外不能使用 python不支持
private 私有类 本类的类内部都能使用,其他地方都不能使用 python支持
'''
2,property装饰器
property装饰器(内置函数)
做了什么? setter delter
property的第一个应用场景
将一个方法伪装成一个属性 print(c1.area)就不需要用括号调用了
from math import pi
class Circle:
def __init__(self, r):
self.r = r
@property # 将一个方法伪装成一个属性 print(c1.area)就不需要用括号调用了
def area(self):
return pi * self.r ** 2
c1 = Circle(5)
print(c1.r)
print(c1.area)
变量的属性和方法? # 属性:圆形的半径/圆形的面积 # 方法:登录/注册 一个动作
import time
class Person:
def __init__(self, name):
self.name = name
self.birth_year = 1999
self.birth_mon = 1
@property
def age(self): # 装饰的这个方法 不能有参数
age = time.localtime().tm_year - self.birth_year
month = time.localtime().tm_mon - self.birth_mon
return (f'{self.name}已经出生{age}年零{month}月')
taibai = Person('taibai')
print(taibai.age)
property的第二个应用场景
一般和私有的属性合作的,将一个方法伪装成一个属性只能看不能改
class User:
def __init__(self,user,pwd):
self.user = user
self.__pwd = pwd
@property
def pwd(self):
return self.__pwd
alex = User('alex', '123456')
print(alex.pwd)
class Goods:
discount = 0.8
def __init__(self,name, origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
apple = Goods('apple', 5)
print(apple.price)
property的进阶
class Goods:
discount = 0.8
def __init__(self,name, origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.setter # 装饰器必须和上面的方法同名
def price(self, new_value): # 这个方法必须和上面的方法同名
if type(new_value) is int: # isinstance(new_price,int) 也可以
self.__price = new_value
@price.deleter
def price(self):
print('执行我了') # del self.__price 这个是真的删除的语句
apple = Goods('apple', 5)
print(apple.price) # 4.0 调用的是被@property装饰的price
apple.price = 10 # 调用的是被setting装饰的price,此时可以修改苹果的价格
print(apple.price) # 8.0
del apple.price # 并不能真的删除什么,只是调用了对应的被@price.deleter装饰的方法而已
3,反射
用字符串数据类型的名字 来操作这个名字对应的函数\实例变量\绑定方法\各种方法
需要的场景: 有些时候你明明知道一个变量的字符串数据类型的名字,你想直接调用它,但是调不到 这个时候需要用到反射
比如:
1,反射对象的实例变量/绑定方法
2,反射类的静态变量/其他方法
3,模块中的所有变量
1,被导入的模块
2,当前执行的py文件--脚本
反射的基本内容 1,hasattr 2,getattr 3,几种情况 反射模块中的内容 反射脚本中的内容 反射对象的属性或者绑定方法 反射类的静态变量 4,callable() 实际的例子 --- 归一化设计
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def qqxing(self):
print('qqxing')
alex = Person('alex', 50)
wusir = Person('wusir', 30)
ret = getattr(alex, 'age')
print(ret) # 50
ret = getattr(wusir, 'age')
print(ret) # 30
ret = getattr(wusir, 'qqxing') # 相当于这个ret得到的是qqxing的内存地址
ret() # qqxing
import a
print(a.Wechat)
print(a.Alipay)
# 对象名.属性名 ==> getattr(对象名,'属性名')
# a.Alipay ==> getattr(a,'Alipay')
print(getattr(a, 'Alipay'))
print(getattr(a, 'Wechat'))
class WeChat: pass
class Alipay: pass
反射模块里的内容
# 反射模块里的内容
import a
import sys
print(sys.modules['a'].Alipay)
print(a.Alipay)
print(getattr(a, 'Alipay'))
print(getattr(sys.modules['a'], 'Alipay'))
反射本文件的内容
wahaha = 'hahahaha'
print(sys.modules) # 获取到本文件的键值
print(getattr(sys.modules['__main__'], 'wahaha')) # 根据键值进行反射
实例用法
class Payment: # 就是一个规范类,主动抛出异常,告诉程序员哪里不对
def pay(self, money):
raise NotADirectoryError('请在子类中重写同名pay方法') # 主动抛出异常
class Alipay(Payment):
def __init__(self, name):
self.name = name
def pay(self, money):
dic = {'username': self.name, 'price': money}
print(f'{self.name}支付宝支付{money}元,成功')
class WeChat(Payment):
def __init__(self, name):
self.name = name
def pay(self, money):
dic = {'username': self.name, 'money': money}
print(f'{self.name}微信支付{money}元,成功')
class Applepay(Payment):
def __init__(self, name):
self.name = name
def fuqian(self, money):
dic = {'username': self.name, 'money': money}
print(f'{self.name}苹果支付{money}元,成功')
# 原来的使用方法
aw = Alipay('alex')
aw.pay(200)
bw = WeChat('wusir')
bw.pay(300)
# 使用反射
import sys
def pay(name, price, kind):
class_name = getattr(sys.modules['__main__'], kind)
obj = class_name(name)
obj.pay(price)
# if kind == 'WeChat':
# obj = WeChat(name)
# elif kind == 'Alipay':
# obj = Alipay(name)
# elif kind == 'Applepay':
# obj = Applepay(name)
# obj.pay(price)
pay('alex', 200, 'Alipay')
pay('alex', 200, 'WeChat')
pay('alex', 200, 'Alipay')
以下是需要记忆的
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
a = A()
print(getattr(a, 'name')) # alex 反射对象的实例化变量
# # 反射对象的绑定方法
print(getattr(a, 'func')()) # <bound method A.func of <__main__.A object at 0x0000021DAAD502C8>> 获得func的地址
getattr(a, 'func')() # wahaha
print(getattr(A, 'Role')) # 反射类的静态变量
# 反射本模块中的内容
import sys
cat = '小a'
dog = '小b'
def pig():
print('小p')
print(getattr(sys.modules['__main__'], 'cat')) # 反射本模块中的实例变量
print(getattr(sys.modules['__main__'], 'dog')) # 反射本模块中的实例变量
getattr(sys.modules['__main__'], 'pig')() # 反射本模块中的方法
4,反射的另一种方法
hasattr
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
a = A()
print(getattr(a, 'name'))
# print(getattr(a, 'sex')) # 会报错
print(hasattr(a, 'name')) # True
print(hasattr(a, 'age')) # True
print(hasattr(a, 'sex')) # False
hasattr可以进行判断属性存不存在
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
if hasattr(a, 'name'):
print(getattr(a, 'name'))
callable()
判断括号内的是不是可调用的 来确定是否加()
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
a = A()
if hasattr(a, 'name'):
if callable(getattr(a, 'name')):
getattr(a, 'name')()
if hasattr(a, 'func'):
if callable(getattr(a, 'func')):
getattr(a, 'func')()
5,反射的例子
文件的操作 ''' 显示所有可以做的操作 1,读文件 2,写文件 3,删除文件 4,文件重命名 5,复制文件 '''
class File:
lst = [('读文件', 'read'), ('写文件', 'writer'), ('删除文件', 'remove'),
('文件重命名', 'rename'), ('复制文件', 'copy'), ('移动', 'move')]
def writer(self):
print('in writer func')
def read(self):
print('in read func')
def remove(self):
print('in remove func')
def rename(self):
print('in rename func')
def copy(self):
print('in copy func')
def move(self):
print('in move func')
f = File()
while True:
for index, opt in enumerate(File.lst, 1):
print(index, opt[0])
num = int(input('请输入您要操作的序号>>>'))
if num <= len(File.lst):
if hasattr(f, File.lst[num-1][1]):
getattr(f, File.lst[num-1][1])()
else:
print(f'请输入1-{len(File.lst)}的数字!')
6,练习题目
# 1
class Authentic:
def __init__(self, name, age):
self.name = name
self.age = age
def register(self):
pass
def login(self):
pass
l = [('登录', 'login'), ('注册', 'register')]
'''
需求;
1,循环这个列表
2,显示序号用户要做的操作
3,用户输入序号
4,你通过序号找到对应的login或者register方法
5,进行实例化
6,调用对应的方法,完成注册和登录功能
'''
# 2
class User:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
pass
def sleep(self):
pass
'''
需求:
1,用户输入用户名,密码和性别
2,实例化对象
3,用户任意输入以下内容:
1,如果输入的是用属性名,打印属性值
2,如果输入的是方法名,调用方法
3,如果输入的什么都不是 不做任何操作
'''
# 3
'''
自定义一个模块,里面有自己实现的mypickle和myjson,只需要传递一个参数'mypickle'还是'myjson'
'''
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客
更多内容可以查看自己学python的过程,简单笔记。-CSDN博客