上节课作业解答
# 通过多重继承方法,分别定义出动物,人类,和和荷兰人三种类 class Animal(object): def __init__(self, name): self.name = name ? def eat(self): print(‘%s正在吃东西‘ % self.name) ? def breath(self): print(‘%s正在呼吸‘ % self.name) ? ? class Person(Animal): def __init__(self, name, money): super().__init__(name) self.money = money ? def speak(self): print(‘%s说他有%s人民币‘ % (self.name, self.money)) ? ? class Fulan(Person): def eat(self): print(‘弗兰人%s不仅爱吃辣,而且爱吃槟榔‘ % self.name) ? def speak(self): print(‘福兰人%s正在blablabla讲弗兰话。‘ % self.name) ? ? juhao = Fulan(‘句号‘, 23) juhao.breath() juhao.eat() juhao.speak() ? ? #拼接一个Spiderman class Spider(Animal): def climb(self): print(‘%s正在攀岩‘ % self.name) ? def tusi(self): print(‘%s正在吐丝‘ % self.name) ? ? class Spiderman(Person, Spider): pass ? ? Spiderman = Spiderman(‘Spiderman‘, 10) Spiderman.tusi() Spiderman.climb() Spiderman.eat() Spiderman.breath() ? #说明: 1. 调用父类的两种方法: Animal.__init__(self.name) super().__init__(name) 2. 不能直接调用__init__,且__init__只能有一个 以上运行结果 句号正在呼吸 弗兰人句号不仅爱吃辣,而且爱吃槟榔 福兰人句号正在blablabla讲弗兰话。 Spiderman正在吐丝 Spiderman正在攀岩 Spiderman正在吃东西 Spiderman正在呼吸
所有的函数都是类(对象)
魔术方法示例:(__方法__)
a = ‘hahaha‘ b = ‘12‘ print(b + a) ? # 等效于 print(b.__add__(a)) ? # 运行结果 # 12hahaha # 12hahaha
示例__add__
# 添加其他属性
# 魔术方法在类中的使用 class Rectangle(object): def __init__(self, length, width): self.length = length self.width = width ? def get_area(self): return self.length * self.width ? def __add__(self, other): add_length = self.length + other.length add_width = self.width + other.width return add_length, add_width
示例__str__
__repr__
str(面向使用者,提供简洁有用信息)
repr(面向开发者,提供接近创建时的信息,让开发者可以通过复制粘贴来重建对象)
直接在交互界面中,直接返回值和print()所使用的(str和repr)魔术方法不同
# str和repr原理 # 例 1 def __str__(self): return ‘length is %s, width is %s‘ % (self.length, self.width) def __repr__(self): return ‘长是%s,宽是%s‘% (self.length, self.width) ? def __call__(self, *args, **kwargs): print(‘我正在被调用‘) rec1 = Rectangle(10, 20) rec2 = Rectangle(30, 40) rec1() print(rec1 + rec2) print(str(rec1)) # (如果不写rec1会返回函数体<……>) print(repr(rec1)) # (如果不写rec1会返回函数体<……>) ? # 运行结果 我正在被调用 (40, 60) length is 10, width is 20 长是10,宽是20 ? # 注: 直接在交互界面中,直接返回值和print()使用的(str和repr)魔术方法不同 # 例 2 a = ‘1,2,3‘ a ‘1,2,3‘ print(a) 1,2,3 ? # 说明: 函数可以直接调用,但是类必须要使用call魔术方法才可以直接调用
__class__ | 查看类名 |
---|---|
__base__ |
查看继承的父类 |
__mro__ |
追根溯源到object,super是基于mro实现的 |
__bases__ |
查看继承的全部父类 |
__dict__ |
查看全部属性,返回属性和属性值键值对形式 |
__doc__ |
查看对象文档,即类中的注释(用引号注释的部分)(注释不能被继承) |
__dir__ |
查看全部属性和方法(等效于dir) |
在初始化函数init之前执行,创建实例
# __new__ a = Rectangle.__new__() Rectangle.__init__(a) ? ? # 单例模式(节省内存) class Esrth(object): def __new__(cls, *args, **kwargs): if not hasattr(cls,‘instance‘): cls.instance = super().__new__(cls) return cls.instance ? def __init__(self): self.name = ‘单例‘ ? a = Esrth() print(id(a)) b = Esrth() print(id(b)) # 把e覆盖了 ? #运行结果 3072614988 3072614988 ? # 说明: 1. 在以上例子中可以看见两个实例的id其实是相同的,意味着这两个实例其实引用的是同一个实例,(只占一个内存)是一个实例的不同名字 2. 其中self代表实例本身,cls代表类本身hasattr判断类中有没有(‘‘)参数 3. 如果没有就调用object中new方法
(一)__new__方法: class Hero(object): ? def __init__(self): print(‘这是init方法‘) ? def __new__(cls): print(‘这个cls是:%s‘ % cls) print(‘这是new方法‘) return object.__new__(cls) ? ? garen = Hero() ? 运行结果: 这个cls是:<class ‘__main__.Hero‘> 这是new方法 这是init方法 ? 说明: 四个点理解__new__方法 1、__new__方法是在 类 创建实例 的时候自动调用的。 2、实例是通过类里面的__new__方法是在 类 创建出来的。 3、先调用__new__方法创建实例,再调用 __init__方法初始化实例。 4、__new__方法,,后面括号里的cls代表的是类本身 在上面的例子中,我们可以看到创建实例的时候,自动调用了__new__,方法和__init__方法,并且是先调用的__new__再调用的__init__方法,打印 cls 的时候显示的这个Hero类
(二)单例模式:
class Hero(object): __instance = None # 定义一个私有属性__instance等于None ? def __new__(cls): if cls.__instance == None: # 然后我们判断它是不是等于None,如果等于None,我们调用父类的方法创建一个实例对象,并把返回的对象赋值给 __instance,并且返回__instance cls.__instance = object.__new__(cls) return cls.__instance else: # 如果__instance不等于None,那就说明已经创建了对象我们直接把__instance返回去。 return cls.__instance ? ? a = Hero() b = Hero() print(id(a)) print(id(b)) ? 打印结果: 3072101708 3072101708 ? # 说明: 单例模式实现的原理:通过重写__new__方法,让__new__只能进行一次实例创建。 在上面的例子中,我们可以看到两个实例的ID是相同的,意味着第二次创建的时候,并没有真正的去创建,而是引用的第一次创的实例,同一个实例的不同名字
作用 | 方法 | 返回 |
---|---|---|
查 | hasattr(re,‘length‘) |
返回bool值 |
getattr(re,‘length‘) |
返回属性值 | |
b.__getattribute__(‘length‘) |
返回全部属性值 | |
改 | setattr(b,‘length‘,6) |
|
b.__setattr__(‘length‘,5) |
||
增 | b.aaa = 1 |
|
setattr(b,‘leg‘,2) |
||
b.__setattr__(‘leg‘,3) |
||
删 | delattr(b,‘leg‘) |
|
b.__delattr__(‘leg‘) |
||
del b |
# 实例: class Rectangle(object): def __init__(self,length,width): self.length = length self.width = width ? def area(self): return self.length * self.width ? a = Rectangle(10,20) print(a.area()) # 查 print(hasattr(a,‘length‘)) # 返回bool值 print(getattr(a,‘length‘)) # 返回属性值 print(a.__getattribute__(‘width‘)) # 返回属性值 # 改 setattr(a,‘length‘,5) a.__setattr__(‘width‘,5) print(a.length) print(a.width) # 增 a.aaa = 1 setattr(a,‘bbb‘,2) a.__setattr__(‘ccc‘,3) print(a.aaa) print(a.bbb) print(a.ccc) # 删 delattr(a,‘ccc‘) a.__delattr__(‘bbb‘) del a # print(a.ccc) # print(a.bbb) # print(a.length) ? 打印结果: 200 True 10 20 5 5 1 2 3 注:print(hasattr(实例rec1,属性‘length‘))等效于print(rec1.__hasattr__(‘name‘))
# 定制属性访问 # 例 __getattr__ ? re = Rectangle(3,4) ? def __getattr__(self,item): print(‘no attribute‘) # 当属性不存在时,若定义了此方法则调用此方法,若存在则返回原值
__getattribute__
b.__getattribute__(‘length‘) # 正常调用返回属性值,属性值不存在,调用__getattr__未定义时会报错
def eat(): return ‘小明在吃东西‘ ? def boom(): return eat() + ‘并且爆炸了‘ ? print(boom()) ? #等效于 def boom(func): return func() + ‘并且爆炸了‘ ? xiaoming = boom(eat) print(xiaoming) ? # 运行结果 小明在吃东西并且爆炸了 小明在吃东西并且爆炸了
可以看到输出时方式不一样,可以修改为以下操作
# 例 1 ? def boom(func): def new_func(): return func() + ‘并且爆炸了‘ return new_func ? xiaoming = boom(eat) print(xiaoming()) ? #运行结果 小明在吃东西并且爆炸了
# 例 2 def eat2(name): return ‘小明和%s在吃东西‘ % name ? def boom2(func2): def new_func2(name): return func2(name) + ‘并且爆炸了‘ return new_func2 ? eat2 = boom2(eat2) print(eat2(‘小红‘)) ? #运行结果 小明和小红在吃东西并且爆炸了
例1 def boom3(func3): def new_func3(name): return func3(name) + ‘并且爆炸了‘ return new_func3 ? ? @boom3 def eat3(name): return ‘小明和%s在吃东西‘ % name ? print(eat3(‘小红‘)) ? # 运行结果 小明和小红在吃东西并且爆炸了
例2 def f1(fu): def func2(): print(‘这是装饰器功能代码‘) fu() ? return func2 ? ? @f1 def func(): print(‘这是基础功能代码‘) ? ? func = f1(func) # 等同@f1 ? func() ? 打印结果: 这是装饰器功能代码 这是装饰器功能代码 这是基础功能代码
class Rectangle: def __init__(self, length, width): self.length = length self.width = width ? def area(self): areas = self.length * self.width return areas ? # 像访问属性一样 @property def areal(self): return self.width *self.length ? ? #静态方法 @staticmethod def func(): #如果写了self在调用时会报错 print(‘staticmethod func‘) ? ? ? #类方法 @classmethod def show(cls): #cls代表类本身 如果加上self在调用时要把实例传入 print(cls) print(‘show fun‘) ? # 用类做装饰器 class TestClass(object): def __init__(self, func): self.func = func ? def __call__(self, *args, **kwargs): print(‘1234‘) return self.func() ? @TestClass def shuzi(): print(‘5678‘) ? shuzi() ? ? # 运行结果 1234 5678
? from datetime import datetime ? ? def run_time(func): def new_func(*args,**kwargs): start_time = datetime.now() print(‘程序开始时间:%s‘ % start_time) func(*args, **kwargs) end_time = datetime.now() print(‘程序结束时间:%s‘ % end_time) print(‘程序总共执行时间:%s‘ % (end_time - start_time)) ? return new_func() ? print(datetime.now()) ? # 运行结果 2018-04-13 17:10:39.332348
原文:https://www.cnblogs.com/zcmq/p/9114111.html