反射

列表最开始放4个值到第5个值的时候开辟一倍的空间

  1. 反射
    1. __hashattr__
    2. __getattr__
    3. __setattr__
  2. 内置函数
    1. __str__
    2. __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)  

\r" 回到行首

考试题讲解

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

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后的东西正常输出

posted @ 2018-09-03 17:37  寓清于浊  阅读(141)  评论(0编辑  收藏  举报