列表最开始放4个值到第5个值的时候开辟一倍的空间
- 反射
__hashattr__
__getattr__
__setattr__
- 内置函数
__str__
__repr__
反射
what
使用字符串数据类型的变量名来获取这个变量的值
why
三个场景
input
文件 从文件中读出字符串,想转换成变量名
网络 将网络传输的字符串转换成变量的名字
反射类中的变量
推荐静态属性,类方法,静态方法
class Foo:
Schoo="oldboy"
Country = "China"
language = "Chinese"
@classmethod
def class_method(cls):
print("ww")
@staticmethod
def static_method():
print("static")
def func(self):
print("")
inp = inp(">>>")
# if inp == "School":print(Foo.School) # 条件判断实现
# if inp == "School":print(Foo.Country)
# if inp == "School":print(Foo.language)
print(getattr(Foo,inp)) #反射实现
"解析getattr方法"
getattr(变量名:命名空间,字符串:属于一个命名空间内的变量名)
Foo.School
getattr(Foo,"School") # Foo.School
"执行类中的方法"
Foo.class_method()
print(getattr(Foo,"class_method")())
getattr(Foo,"static_method")()
getattr(Foo,"func")() #Foo.func(1) 不推荐调用对象方法. 通过对象调用
getattr(Foo,"shuangwaiwai") #没有,会报错。
"避免不报错"
if hasattr(Foo,"shuangwaiwai"):
getattr(Foo,"shuangwaiwai")
反射对象中的变量
getattr(Foo(),"func")()
反射模块中的变量
import os
os.rename("path")
getattr(os,"rename")
反射本文件中的变量
a = 1
b = 2
import sys
print(sys.modules["__main__"]) ##本文件的命名空间
print(sys.modules["__main__"],a)
print(__name__) #内置变量,字符串类型,
import sys
print(sys.modules[__name__]) #反射本文件中的变量 固定使用使用这个命名空间。
class Foo:
a = "b"
import sys
print(getattr(sys.modules[__name__],"Foo").a)
hasattr
getattr
setattr
class Foo:
pass
# Foo.School = "oldboy"
def func():pass
setattr(Foo,"School","OLDBOY")
print(Foo.__dict__)
"往类,对象,空间里添加方法,永远不能变成方法,只是普通函数。
但没人这么做。"
setattr(Foo,"func",func)
class Foo:
a = "b"
import sys
print(setattr(sys.modules[__name__].Foo,"bobo",15))
print(Foo.__dict__)
delattr
print(Foo.__dict__)
delattr(Foo)
wehre
作业
场景 角色 类 属性 - 方法
站在每个角色的角度上思考程序执行的流程
学生选课,需要1. 学生账号,有课程
管理员 创建学生账号,课程管理员创建。
应该先站在管理员的角度上来开发。
登录必须能够自动识别身份,用户名,密码,身份
角色登录使用反射
内置方法
在不是需要程序员定义,本身就存在在类中的方法就是内置方法
名字:双下方法,魔术方法,内置方法
__init__
不需要我们主动调用,而是在实例化的时候内部自动调用的
所有的双下方法啊,都不需要我们直接去调用。都有另外一种自动触发它的语法
__str__
,__repr__
class Course:
def __init__(self.name,period,price,teacher):
self.name = name
self.period = period
self.price = price
self.teacher = teacher
def __str__(self):
return ""%()
course_list = []
python = Course("python","6 month",29800,"bass jon")
linux = Course("linux","5 month",25800,"oldboy")
course_lst.append(linux)
for id,course in enumerate(course_lst,1):
print("" % ())
print(id,course)
#学生选课时,要显示所有的课程
str 何时触发
当你使用%s格式化的时候触发__str__
当你打印一个对象的时候触发__str__
str强转数据类型时 触发__str___
repr
repr 是str的备胎
有__str__的时候执行__str__,没有实现执行__repr__
repr(obj)内置函数对应的结果是__repr__的返回值
当你使用%r格式化的时候触发__repr__
print(repr(course))
print("%r"%course)
# 查找顺序是 子str -> 父 str -> 子repr ->父repr
class Foo:
def __str__(self): #必须return 字符串不然会报错。
return "Foo str"
def __repr__(self):
return "Foo repr"
class Son(Foo):
def __str__(self): #必须return 字符串不然会报错。
return "Son str"
def __repr__(self):
return "Son repr"
s1 = Son()
print(s1)
" 回到行首
考试题讲解
def outer():
name = "alex"
def inner():
# name = "wupeiqi"
print(name)
print(inner.__closure__)
outer()
闭包:装饰器,做缓存
from urllib.request import urlopen
def get_url(url):
ret = urlopen(url)
content = ret.read().decode("ut8")
def get():
if content:
return content
else:
return get
get_url("http://www.douban.com")
查看特性的fget,fset,fdel
class Person:
def __init__(self,first_name):
self._first_name = first_name
@property
def lirst_name(self):
return self._first_name
@lirst_name.setter
def lirst_name(self,value):
if not isinstance(value,str):
raise TypeError("Expected a string")
self._first_name = value
@lirst_name.deleter
def lirst_name(self):
raise AttributeError("Cant delete attribute")
a = Person("Guido")
print(Person.lirst_name.fget)
Python代码被集成到一个大型基础平台架构或程序中。
一个Python类准备加入到一个基于远程过程调用的大型分布式系统中。
这种情况下,直接使用get/set方法(普通方法调用)而不是property或许会更容易兼容。
类名调用形成的问题
class Base:
def __init__(self):
print("Base:init")
class A(Base):
def __init__(self):
Base.__init__(self)
print("A.init")
class B(Base):
def __init__(self):
Base.__init__(self)
print("B.init")
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print("C.init")
c= C()
class Base:
def __init__(self):
print("Base:init")
class A(Base):
def __init__(self):
super().__init__()
print("A.init")
class B(Base):
def __init__(self):
super().__init__()
print("B.init")
class C(A,B):
def __init__(self):
super().__init__()
print("C.init")
c= C()
class Base:
def __init__(self):
print("Base:init")
class A(Base):
def __init__(self):
super().__init__()
print("A.init")
class B(Base):
def __init__(self):
super().__init__()
print("B.init")
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print("C.init")
c= C()
只重定义父类某一个特性方法
class Person:
def __init__(self,name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self,value):
if not isinstance(value,str):
raise TypeError("Expected a string")
self._name = value
@name.deleter
def name(self):
raise AttributeError("cant delete")
class SubPerson(Person):
@Person.name.getter
def name(self):
print("get name")
return super().name
类方法的一个主要用途就是定义多个构造器
import builtins
vars(builtins)
三元运算是两种结果与if elif else是两种操作
if j.startswith("组长"):
gno = 1
else:
gno += 1
True if j.startswith("组长") else False
mkdir day{1..10}
awk sed grep
特性是不可被调用的
特性有文档,并且需要通过类调用特性中的文档
D.x.fget__doc__
D.x.fset__doc__
D.x.fdel__doc__
当我们获得类的__dict__时自定义的私有成员已经改变了名称
所以当我们过滤时,要用单下划线
class D:
def __create_students(self):
pass
D.__dict__
----------
"输出"
_Watcher__create_students
----------
为什么会出现包?
因为一个文件内多个类的遍历需要的时间是一个文件一个类时间的n倍
函数内pass后的东西正常输出