饮冰三年-人工智能-Python-18Python面向对象

本文深入探讨Python中类与对象的高级特性,包括类属性、实例属性的修改,静态属性、方法和类方法的使用,以及组合、继承、多态的概念与实践。此外,还介绍了封装、反射、迭代器、上下文管理、描述符、元类等高级主题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 类与实例对方法和属性的修改

class Chinese:
    # 这是一个Chinese的类
    #定义一个类属性,又称为静态数据或者静态变量,相当于C#中的static
    country="China"
    # 定义一个初始化函数,
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender
    #定义一个方法
    def play(self,ballName):
        print('%s 正在打 %s' %(self.name,ballName))

#1类属性
print("----------开始修改类属性")
#1.1 查看类属性
print(Chinese.country) #China
#1.2 修改类属性
Chinese.country="中华人民共和国"
print(Chinese.country) #中华人民共和国
#1.3 删除类属性
del Chinese.country
print(Chinese.__dict__)
#{'__module__': '__main__', '__init__': <function Chinese.__init__ at 0x0000000001D30EA0>, 'play': <function Chinese.play at 0x000000000247C7B8>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None}
#1.4 添加类属性
Chinese.country="中国"
print(Chinese.__dict__)
#{'__module__': '__main__', '__init__': <function Chinese.__init__ at 0x0000000002300EA0>, 'play': <function Chinese.play at 0x000000000250C7B8>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'country': '中国'}

#2方法属性
print("----------开始修改方法属性")
#2.1 查看方法属性
p1=Chinese('张三',18,"")
Chinese.play(p1,'篮球') #张三 正在打 篮球
#2.2 修改方法属性
def play(self,ballName,address):
    print('%s 在%s打%s' %(self.name,address,ballName))
Chinese.play=play
Chinese.play(p1,'篮球','操场') #张三 在操场打篮球
#2.3 删除类属性
del Chinese.play
print(Chinese.__dict__)
#{'__module__': '__main__', '__init__': <function Chinese.__init__ at 0x0000000001D40EA0>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'country': '中国'}
#2.4 添加方法
def eat(self,food):
    print("%s 正在吃 %s" %(self.name,food))
Chinese.eat=eat
print(Chinese.__dict__)
# {'__module__': '__main__', '__init__': <function Chinese.__init__ at 0x0000000001D40EA0>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'country': '中国', 'eat': <function eat at 0x0000000001DFC7B8>}

#3实例类属性
print("----------开始修改实例类属性")
#3.1 查看实例类属性
p=Chinese('张三',18,"")
print(p.country) #中国
#3.2 修改实例类属性
p.country="中华人民共和国"
print(p.country) #中华人民共和国
#3.3 删除实例类属性
del p.country
print(p.__dict__)
#{'name': '张三', 'age': 18, 'gender': '男'}
# 3.4 添加类属性
p.country="中国"
print(p.__dict__)
#{'name': '张三', 'age': 18, 'gender': '男', 'country': '中国'}

print("----------开始修改实例属性")
#4.1 查看实例类属性
p=Chinese('张三',18,"")
print(p.name) #张三
#4.2 修改实例类属性
p.name="张三三"
print(p.name) #张三三
#4.3 删除实例类属性
del p.name
print(p.__dict__)
#{'age': 18, 'gender': '男'}
# 4.4 添加类属性
p.name="张三三"
print(p.__dict__)
#{'age': 18, 'gender': '男', 'name': '张三三'}

print("----------开始修改实例方法")
#4.1 查看实例方法
p=Chinese('张三',18,"")
p.eat('包子')
# 张三 正在吃 包子
#4.2 修改实例类属性
def eat(self,food,address):
    print('%s在%s吃%s' %(self.name,address,food))
p.eat=eat
p.name="张三三"
p.eat(p,"包子","食堂") #张三三在食堂吃包子
#4.3 删除实例类属性
del p.eat
print(p.__dict__)
#{'name': '张三三', 'age': 18, 'gender': '男'}
# 4.4 添加实例方法属性
def study(self,cont):
    print('%s学%s' % (self.name,cont))
p.study = study
p.study(p,'python')
print(p.__dict__)
#张三三学python
# {'name': '张三三', 'age': 18, 'gender': '男', 'study': <function study at 0x0000000002526B70>}
ViewCode

2 静态属性、静态方法、类方法

class Room:
    owner="China"
    # 这是一个房间的类
    def __init__(self,name,width,length,height):
        self.name=name
        self.width=width
        self.length =length
        self.height=height
    @property
    # 这是一个方法,但是通过@property装饰后,就变成了一个静态方法,可以通过.方法名调用
    def getArea(self):
        return self.width*self.length
    @classmethod
    # 这是一个方法,但是通过@classmethod装饰后,就变成了一个类方法,可以类调用,不用实例化
    def getOwner(cls):
        print("房产所有者"+cls.owner)
    @staticmethod
    # 这是一个方法,但是通过@staticmethod装饰后,就变成了一个静态方法,可以在调用处直接传递参数
    # 用户输入想要的面积和折扣,可以计算出价格
    def getPrice(area,discount):
       return area*20000*discount/10

r1=Room("天字一号房",10,20,2)
print('房间面积'+str(r1.getArea)) #房间面积200
#类方法:可以通过类名直接调用方法
Room.getOwner() #房产所有者China
#静态方法,可以传递一些与类关联不大的数据
print(r1.getPrice(r1.getArea,9)) #3600000.0
View Code

3 组合(大类包含小类)

class School:
    # 这是一个学校类
    def __init__(self,name,address):
        self.name=name
        self.address=address
class Courses:
    # 这是一个课程类,组合了一个学校
    def __init__(self, name, cycle,price,schoolObj):
        self.name = name
        self.cycle = cycle
        self.price = price
        self.school = schoolObj
    def getInfo(self):
        print('%s 正在开设 %s' %(self.school.name,self.name))
school = School('北大','北京')
Courses('python','100','10',school).getInfo()
View Code

4 继承

#继承一:抽象出共有的父类,实现继承
class Animal:
    def __init__(self,name):
        self.name=name
    def eat(self):
        print('%s会吃' %(self.name))
    def bark(self):
        print('%s会叫' %self.name)
class Dog(Animal):
    pass
class Cat(Animal):
    pass

dog=Dog("小黄")
dog.bark()
cat = Cat("伊丽莎白")
cat.eat()
#继承二:但是猫和狗的叫声不同,所以常用的是接口继承(父类只提供一个规范,子类在调用时需要实现这些规范)
# 如果是抽象方法,子类必须实现
import abc
class Animal(metaclass=abc.ABCMeta):
    def __init__(self,name):
        self.name=name
    @abc.abstractclassmethod
    def eat(self):
        print('%s会吃' %(self.name))
    def bark(self):
        print('%s会叫' %self.name)
class Dog(Animal):
    def bark(self):
        print('%s会汪汪叫' %self.name)
    #如果是抽象方法,子类必须实现
    def eat(self):
        pass
class Cat(Animal):
    def eat(self):
        print('%s会吃鱼儿' %self.name)

dog=Dog("小黄")
dog.bark()
cat = Cat("伊丽莎白")
cat.eat()
两种继承方式

  4.1 继承顺序

  当类是经典类(class C1:)时,多继承情况下,深度优先(依次找到根节点)

  当类是新式类(class C1(object):)时,多继承情况下,广度优先(最后一次才找到根节点)

  原理:python会计算一个方法解析顺序(MRO)列表,可通过print(类名.__mro__)查看

  4.2 子类中调用父类的方法

class Vehicle:
    def __init__(self,name,speed,load):
        self.name=name
        self.speed = speed
        self.load = load
    def run(self):
        print('%s开始启动' %(self.name))

class Subway(Vehicle):
    def __init__(self,name,speed,load,line):
        Vehicle.__init__(self,name,speed,load)
        self.line = line
    def run(self):
        Vehicle.run(self)
        print("时速:"+self.speed)
class Car(Vehicle):
    # 使用super减少了self字段的传递,而且如果父类类名修改的话,子类继承不用改变
    def __init__(self,name,speed,load,brand):
        super().__init__(name,speed,load)
        self.brand = brand
    def run(self):
        super().run()
        print("品牌:"+self.brand)

#测试数据
sub=Subway("地铁","300km/h","20000","2号线")
sub.run()

cr=Car("汽车","80km/h","5","红旗")
cr.run()
两种方式实现继承

 5 多态

  类的继承有两成意义:改变+扩展。多态就是累的这两层意义的一个具体的实现机制。在不考虑实例(子类)类型的情况下,使用子类。即调用不同的实例化对象下的相同方法,时间的过程不同

class H2O:
    def __init__(self,name,temp):
        self.name=name
        self.temp = temp
    def currentStatus(self):
        if self.temp < 0:
            print("在101.325kPa下,当前状态为:冰")
        elif self.temp == 0:
            print("在101.325kPa下,当前状态可能是:冰水混合物")
        elif self.temp < 100:
            print("在101.325kPa下,当前状态为:水")
        elif self.temp > 100:
            print("在101.325kPa下,当前状态为:水蒸气")
class Ice(H2O):
    pass
class Water(H2O):
    pass
class Steam(H2O):
    pass

ice = Ice("",-10)
water = Water("",10)
steam= Steam("水蒸气",101)

ice.currentStatus();water.currentStatus();steam.currentStatus();
水的三种状态

 6 封装 明确区分内外,其实不能真正不被外部访问。内部实现逻辑,外部无需知晓,并且为封装到内部的逻辑提供一个供外部访问的接口  

 约定:_开头定义

 __开头,其实在外部调用的时候python默认修改了名“_类名_定义名“

class People:
    _plate="地球"
    def __init__(self,name,age):
        self.name=name
        self._age=age

p=People("张三",12)
print(p._plate) #地球
print(p._age)   #12
'''虽然以_开头但是还可以被访问到,因为这只是一种约定'''
class People2:
    __plate="地球"
    def __init__(self,name,age):
        self.name=name
        self.__age=age

p=People2("张三",12)
#print(p.__plate) #报错 AttributeError: 'People2' object has no attribute '__plate'
print(p._People2__plate)  #地球
print(p._People2__age)   #12
'''虽然以__开头不可以被直接访问到,但可以通过“_+类名+自定义名称'''
class People3:
    __plate="地球"
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    # 外部现在是无法通过属性名调用了,但是目前有一个需求:就是要获取年龄,这个时候还可以通过定义接口的方法实现
    def getAge(self):
        return self.__age;
p3=People3("张三",12)
print(p3.getAge())
View Code

没有必要的封装,不可取

7 反射:自省,自己检测自己。主要指程序可以访问、检测和修改它本身状态或行为的一种能力

# 反射:自省,自己检测自己。主要指程序可以访问、检测和修改它本身状态或行为的一种能力
class Animal:
    able="Run"
    def __init__(self,name):
        self.name=name
    def eat(self):
        print('%s会吃' %(self.name))
    def bark(self):
        print('%s会叫' %self.name)
a1=Animal("Dog")
print(a1.name)
print(a1.__dict__["name"])
# a1.name 等价于 a1.__dict__["name"]
# 1 hasattr(object,name) 判断object中有没有一个name字符串对应的方法或属性
print(hasattr(a1,'able')) #True
print(hasattr(a1,'eat')) #True
print(a1.__dict__)  #{'name': 'Dog'}
# 虽然__dict__中没有eat方法,但是,这里只是检查能否调用到
# 2 getattr(object,name) 等价于 a1.属性或方法  获取对应的方法或属性
print(getattr(a1,'able')) #Run
print(getattr(a1,'eat')) #<bound method Animal.eat of <__main__.Animal object at 0x0000000002564630>>
# 如果没有就报错,通过默认参数的方法可以不报错
print(getattr(a1,'11111',"该属性不存在"))
print(getattr(a1,'2222',"该方法不存在"))
# 3 getattr(object,k,v) 等价于 a1.属性或方法=''  判断设置对应的方法或属性
setattr(a1,'able2','run')  #创建
setattr(a1,'able','drink') #修改
print(getattr(a1,'able')) #drink
print(getattr(a1,'able2')) #run
# 4 delattr(object,k,v) 删除对应的方法或属性
delattr(a1,'able')
View Code
# 反射:自省,自己检测自己。主要指程序可以访问、检测和修改它本身状态或行为的一种能力
class Animal:
    able="Run"
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print('%s会吃' %(self.name))
    def bark(self):
        print('%s会叫' %self.name)

    def __getattr__(self, item):
        print("调用__getattr__(self, item)方法")
    # __setattr__()方法不常用,但可以通过重写该方法,实现自己特殊的需求,如类型只能是字符串
    def __setattr__(self, key, value):
        if key.strip()=="name":
            if type(value) is str:
                self.__dict__[key] = value
            else:
                print("name必须是字符串")
        else:
            self.__dict__[key] = value
    def __delattr__(self,item):
        self.__dict__.pop(item)
a1=Animal("Dog",12)
# __开头表示内置属性
# 修改属性
a1.__setattr__('name',15)
print(a1.__dict__) #{'name': 'Dog', 'age': 12}
del a1.name #调用__delattr__(self, item)方法
# 只有在属性不存在的时候会触发__getattr__
print(a1.abccccc)
反射2
# 导入其他模块进行反射
import pkage1.say as p

print(hasattr(p,"sayHello"))
print(getattr(p,"sayHello111","不存在"))
导入其他模块进行反射

8 二次加工标准类型

# 方法1,通过继承实现
class ListYK(list):
    # 添加一个新方法,求取中间值
    def show_middle(self):
        mid_index=int(len(self)/2)
        return self[mid_index]

    # 重写一个添加方法,只能添加字符串
    def append(self,p_object):
        if type(p_object) is str:
            # list.append(self,p_object)
            super().append(p_object)
l1=ListYK("hello")
print(l1.show_middle()) #l
l1.append("1")
l1.append(2)
print(l1) #['h', 'e', 'l', 'l', 'o', '1']

# 2授权:授权时包装的一个特性,包装一个类型通常是对已存在的类型的一些定制
# 授权的过程,及时所有更新的功能都是有新类的某部分来处理,但已存在的功能就授权给队形的默认属性
import time
class OpenNew:
    def __init__(self,filename,mode='r',encoding="utf-8"):
        self.file=open(filename,mode,encoding=encoding)
        self.filename=filename
        self.mode = mode
        self.encoding = encoding
    def __getattr__(self, item):
        return getattr(self.file,item)
    def write(self,line):
        t = time.strftime('%Y-%m-%d %T')
        self.file.write('%s %s' % (t, line))
f1=OpenNew("a.txt","w+","utf-8")
f1.write("111\r\n")
f1.write("222")
View Code

9 __getattribute__与__getattr__

#__getattribute__与__getattr__

# 1:只有__getattr__存在的情况下,只有获取的属性不存在,才触发此方法

class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def getInfo(self):
        return "My name is %s,I am %s years old" % (self.name, self.age)
    def __getattr__(self,item):
        print("我是__getattr")

f = Foo("Mr.zhang", 18)
f.name
f.agea  #只有属性不存在的时候,才会触发

class Foo2:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def getInfo(self):
        return "My name is %s,I am %s years old" % (self.name, self.age)
    def __getattribute__(self, item):
        print("我是__getattribute__")

f2 = Foo2("Mr.zhang", 18)
f2.name
f2.agea
#不管是否存在,都会触发__getattribute__方法
class Foo3:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def getInfo(self):
        return "My name is %s,I am %s years old" % (self.name, self.age)

    def __getattribute__(self, item):
        print("我是__getattribute__")
        raise AttributeError("属性不存在,就会触发getattr方法")
    def __getattr__(self, item):
        print("我是__getattr")
print("F3=======>")
f3 = Foo3("Mr.zhang", 18)
f3.name
f3.agea
# 不管是否存在,都会触发__getattribute__方法,当都_getattribute__方法抛出AttributeError异常时,触发__getattr__方法
#__getattribute__与__getattr__

10 __item__

class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def getInfo(self):
        return "My name is %s,I am %s years old" % (self.name, self.age)
    def __getitem__(self, item):
        print("我是__getitem__方法")
        return self.__dict__[item]
    def __setitem__(self, key, value):
         self.__dict__[key]=value
    def __delitem__(self, key):
        self.__dict__.pop(self.__dict__[key])


f = Foo("Mr.zhang", 18)
print(f["name"])
f["age"]="12"
print(f["age"])
del  f.age
print(f.__dict__)
'''
我是__getitem__方法
Mr.zhang
我是__getitem__方法
12
{'name': 'Mr.zhang'}
'''
View Code

11 __str__与__repr__

# 注意:这两个方法的返回值必须是字符串
# 如果__str__没有定义,那么就会__repr__替代
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return ("我叫%s 今年%s岁了" %(self.name,self.age))

    def __repr__(self):
        return ("我今年%s岁了 叫%s " % (self.age,self.name))

f=Foo("杨可",26)
print(f)
#str函数或者print函数 --》obj.__str__()
#repr或者交互式解释器--》obj.__repr__()
#如果__str__没有被定义,那么就会使用__repr__来代替
__str__ __repr__

12 查看实例的来源

from pkage1.Foo import Foo

f = Foo()
print(f.__module__)
print(f.__class__)
# pkage1.Foo
# <class 'pkage1.Foo.Foo'>
View Code

13 析构函数

class Foo:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print("析构函数")
f = Foo("zhangsan")
del f
View Code

14 利用 ()可以执行

class Foo:
    def __call__(self, *args, **kwargs):
        print("实例执行了call方法")
f=Foo()
f()
# 实例执行了call方法
call方法

15 迭代器协议

# 迭代器协议:有一个iter方法,有一个next方法,有Stopiteration终止
class Foo:

    def __init__(self,x,prv=0,cur=1):
        self.x=x
        self.prv = prv
        self.cur = cur
    def __iter__(self):
        return self
    def __next__(self):
        if self.x>100:
            raise StopIteration("越界了")
        self.x =  self.prv + self.cur
        self.prv =self.cur
        self.cur= self.x
        return self.cur
f =Foo(10)
print(f.__next__())
print(next(f))

print("====>")
for i in f:
    print(i)

# 1
# 2
# ====>
# 3
# 5
# 8
# 13
# 21
# 34
# 55
# 89
# 144
斐波那契数列

 16 上下文管理协议

# 上下文管理协议
# with obj as  f 等同于 f=obj.__enter__()
# 执行代码块
# 一:没有异常,整个代码块运行完毕后触发__exit__,它的三个参数都为None
# 二:出现异常,直接触发__exit__
#     a:如果__exit__的返回值为True,代表吞掉了异常
#     b:如果__exit__的返回值不为True,代表吐出来异常
#     c:__exit__的运行完毕,代表整个with语句执行完毕
class OpenNew:
    def __init__(self,name):
        self.name = name
    def __enter__(self):
        print('执行enter')
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("执行exit方法")
        print("3")
        print(aa)
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        print("4")
        return True
with OpenNew("a.txt") as  f:
    print('1')
    print('2')
print('5')
View Code

 17 描述符

#描述符协议:描述符本质就是一个新式类,至少实现了__get__(),__set__(),__delete__()中的至少一个
# __get__(),调用属性时触发
# __set__(),为属性赋值是触发
# __delete__(),删除属性时触发
# 描述符作用:可以用来定义一个类的属性,
# 描述符的特性:由该类产生的实例变化时候不会调用这些个方法,定义另外一个属性时,会被调用
# 描述符分类:没有实现__set__()的叫非数据描述符,实现了__set__()和__get__()的叫数据描述符
# 注意事项:1:描述符本身和被代理类都是新式类,2:定义成类的属性,,不能定义到构造函数中
#定义一个描述符
class StrNew:
    def __get__(self, instance, owner):
        print("Str调用__get__")
    def __set__(self, instance, value):
        print("Str调用__set__")
    def __delete__(self, instance):
        print("Str调用__delete__")
class IntNew:
    def __get__(self, instance, owner):
        print("Int调用__get__")
    def __set__(self, instance, value):
        print("Int调用__set__")
    def __delete__(self, instance):
        print("Int调用__delete__")
class People:
    name=StrNew()
    age=IntNew()
    def __init__(self,name,age):
        self.name=name
        self.age=age
p=People('张三',15)
p.name
p.name="张三New"
del  p.name
p.age
p.age=15
del p.age

# 优先级
# 1:类属性>2:数据描述符>3:实例属性>4:非数据描述符>5:找不到属性触发__getattr__()
# print("1:类属性>2:数据描述符")
# People.name #调用类属性name 本质是调用描述符__get__()方法
# People.name="zhangsan" #它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的
# del People.name

print("2:数据描述符>3:实例属性")
p=People('张三',15)
p.name="lisi"
print(p.__dict__)  #{}
# 与实例相关的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,操作都是跟描述符有关,与实例无关了
描述符协议
# python 是弱类型,可以通过描述将其设置为强类型
# 定义一个类型控制的描述符
class TypeControl:
    # 定义一个构造函数,用于初始化,字段名称(根据名称对其进行设置)和类型(设置值是做判断)
    def __init__(self,name,typeName):
        self.name=name
        self.typeName = typeName
    def __get__(self, instance, owner):
        print("调用__get__")
        return instance.__dict__[self.name]
    def __set__(self, instance, value):
        print("调用__set__")
        # //如果设置值的属性和定义的属性不一致,报错
        if not isinstance(value,self.typeName):
            raise TypeError
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print("调用__delete__")
        instance.__dict__.pop(self.name)

class People:
    name=TypeControl("name",str)
    age=TypeControl("age",int)
    def __init__(self,name,age):
        self.name=name
        self.age=age

p=People('张三',15)
p.name
del p.name

p=People('1',1)
p.name
del p.name
定义一个类型控制的描述符

18 装饰器

# 装饰器=高阶函数+函数嵌套+闭包
# 高阶函数:传入参数或输出结果是一个函数
# 函数嵌套:函数中定义函数
import time
# 添加一个参数,如果参数是n就打n折
def disCount(n=1):
    def timmer(func):
        def wrapper(*args,**kwargs):
            startTime= time.time()
            res=func(*args,**kwargs)*n;
            endTime= time.time()
            print("今天是国庆节,每位客户打的折扣为:"+str(n*10))
            return  res
        return wrapper
    return timmer
#@timmer  #语法糖,相当于#test=timmer(test)
@disCount(n=0.9)
def test(a,b):
    return a+b

print(test(100,200))
装饰器
# 定义一个用户列表
userList=[{"name":"zhangsan","pwd":"333"},{"name":"lisi","pwd":"444"},{"name":"wangwu","pwd":"555"}]
currentUser={"name":"None","loginState":"False"}
def SignOut():
    currentUser = {"name": "None", "loginState": "False"}

def authority(func):
    def wapper(*args,**kwargs):
        if currentUser["name"] and eval(currentUser["loginState"]):
            res = func(*args,**kwargs)
            return res
        else:
            SignIn();
    return wapper
def index():
    print("欢迎来到登录页面")
@authority
def home():
    print("欢迎回家%s" %currentUser["name"])
@authority
def shopping_car():
    print("%s的购物车中有:苹果、葡萄。" %currentUser["name"])

def SignIn():
    print("请先登录")
    userName = input('用户名:').strip()
    userPwd = input('密码:').strip()
    for userInfo in userList:
        if userInfo["name"] == userName and userInfo["pwd"] == userPwd:
            currentUser["name"] = userName
            currentUser["loginState"] = "True"
    if currentUser["name"] and eval(currentUser["loginState"]):
        print("登录成功,")
    else:
        print("用户名或密码错误")
        SignIn()
index()
home()
shopping_car()
装饰器,修饰方法
class TypeControl:
    # 定义一个构造函数,用于初始化,字段名称(根据名称对其进行设置)和类型(设置值是做判断)
    def __init__(self,name,typeName):
        self.name=name
        self.typeName = typeName
    def __get__(self, instance, owner):
        print("调用__get__")
        return instance.__dict__[self.name]
    def __set__(self, instance, value):
        print("调用__set__")
        # //如果设置值的属性和定义的属性不一致,报错
        if not isinstance(value,self.typeName):
            raise TypeError
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print("调用__delete__")
        instance.__dict__.pop(self.name)

def typeAssert(**kwargs):
    def decorateClass(cls):
        for name,expected_type in kwargs.items():
            setattr(cls,name,TypeControl(name,expected_type)) #People.name = TypeControl('name',str)
        return cls
    return decorateClass

#传递字典参数,运行typeAssert(),返回decorateClass
# 继续执行@decorateClass
# 执行@decorateClass给类添加属性
@typeAssert(name=str,age=int)
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age

p=People('张三',15)
p.name
del p.name
装饰器,修饰类

 19 自定义Property属性

class myProperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, owner):
        # 描述符中调用func函数
        # 直接用类调用会由于instance是None,导致运行func()报错
        if instance is None:
            return self
        return self.func(instance)
class Room:
    def __init__(self,name,length,width):
        self.name=name
        self.length=length
        self.width = width
    @myProperty #getArea=myProperty(getArea)
    def getArea(self):
        return self.width*self.length
r1=Room("卧室",6,4)
print(r1.getArea)
print(Room.getArea)
# 思路@myProperty相当于getArea=myProperty(getArea)
#1:定义一个getArea=myProperty(getArea)
#2:其中定义一个构造函数,接收传递过来的函数名并返回,相当于类的装饰器功能
#3:要想通过.方法名掉用方法。需要通过描述符(3:实例属性>4:非数据描述符)
自定义属性myProperty
class myProperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, owner):
        print("get")
        # 描述符中调用func函数
        # 直接用类调用会由于instance是None,导致运行func()报错
        if instance is None:
            return self
        res = self.func(instance)
        setattr(instance,self.func.__name__,res)
        return res
class Room:
    def __init__(self,name,length,width):
        self.name=name
        self.length=length
        self.width = width
    @myProperty #getArea=myProperty(getArea)
    def getArea(self):
        return self.width*self.length
r1=Room("卧室",6,4)
print(r1.getArea)
print(Room.getArea)
print("=======>懒加载,只调用一次,原理:把getArea添加到r1的数据字典中,然后直接从字典中获取")
print(r1.getArea)
print(r1.getArea)
print(r1.getArea)

# 思路@myProperty相当于getArea=myProperty(getArea)
#1:定义一个getArea=myProperty(getArea)
#2:其中定义一个构造函数,接收传递过来的函数名并返回,相当于类的装饰器功能
#3:要想通过.方法名掉用方法。需要通过描述符(3:实例属性>4:非数据描述符)
懒加载myProperty

 20 元类

# 我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type
# print(type(Foo)) # 结果为<class 'type'>,证明是调用了type这个元类而产生的Foo,即默认的元类为type
#
# class关键字在帮我们创建类时,必然帮我们调用了元类OldboyTeacher=type(...),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是
# 1、类名class_name='Foo'
# 2、基类们class_bases=(object,)
# 3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的
# 调用type时会依次传入以上三个参数
class MyType(type):
    def __init__(self):
        print("")
    def __call__(self, *args, **kwargs):
        # 此时self 是Foo,
        #object.__new__(self) 相当于以Foo为类创建对象,即:产生f1
        obj=object.__new__(self)
        #调用Foo下面的init方法
        self.__init__(self,*args, **kwargs)
class Foo(metaclass=MyType):
    def __init__(self,name):
        self.name=name
View Code

 

转载于:https://www.cnblogs.com/YK2012/p/9748654.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值