一、两个装饰器@classmethod、@staticmethod

@classmethod:把类中的绑定方法变成一个类方法,cls 就等于类名

有什么用?

1、在方法中任然可以引用类中的静态变量

2、可以不用实例化对象,就直接用类名在外部调用这个方法

什么时候用?

1、定义了一个方法,默认传 self ,但这个 self 没有被使用。

2、并且你在这个方法里用到了当前类名,或者你准备使用这个类的内存空间中的名字的时候

# 商品打折:
class Goods:
__discount = 0.8

def __init__(self, original_price):
self.original_price = original_price
self.price = self.original_price * self.__discount

@classmethod # 把一个对象的绑定方法改成一个类方法
def change_discount(cls, count):
cls.__discount = count # 相当于Goods.__discount = count


Goods.change_discount(0.6) # 类方法可以通过类名调用

# 实例化一个华为手机对象
huawei = Goods(20)
print(int(huawei.price))

huawei.change_discount(0.4) # 类方法可以通过对象调用

# 实例化一个苹果手机对象
apple = Goods(20)
print(int(apple.price))

# 输出
12
8

扩展:

在掉用类的函数的时候就实例化了一个对象

import time

class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day

@classmethod
def today(cls):
structure = time.localtime()
# 在方法中创建一个对象
obj = cls(structure.tm_year, structure.tm_mon, structure.tm_mday)
return obj


# 当调用类中的today方法就会返回一个对象(对象属性不用自己填,today方法已经填好了)
data对象 = Date.today()
print(data对象.year)
print(data对象.month)
print(data对象.day)

# 输出
2021
5
4

@staticmethod:被装饰的方法会成为一个静态方法

本身是一个普通函数,被挪到类的内部执行,那么直接给这个函数添加 @staticmethod 装饰器就可以了

在函数的内部即用不到 self 变量,也用不到 cls 类

class User:
pass

@staticmethod
def login(user):
print(f'{user},登录成功')

User.login('Alen') # 类可以调佣
Bob = User()
Bob.login('Bob') # 对象可以调佣
# 输出
Alen,登录成功
Bob,登录成功

总结:能定义到类中的内容。

1、静态变量:是个所有的对象共享的变量 ——由对象、类调用

2、实例变量:是对象的属性变量 ——由对象调用

3、绑定方法:是个自带self参数的函数 ——由对象调用

4、类方法:是个自带cls参数的函数 ——由对象、类调用

5、property属性:是个伪装属性的方法 ——由对象调用,但不加括号

二、内置魔术方法

__call__方法:对象 + ( ) 调用这个类中的__call__方法

class User:
pass

@staticmethod
def login(user):
print(f'{user},登录成功')

User.login('Alen') # 类可以调佣
Bob = User()
Bob.login('Bob') # 对象可以调佣
# 输出
Alen,登录成功
Bob,登录成功

__len__方法:len (对象) 需要实现这个类中的__len__方法

class A:
def __init__(self):
self.lis = [1, 2, 3, 4, 5]

def len(self):
return len(self.lis)

def __len__(self):
return len(self.lis)


a = A()
print(len(a)) # 可以直接len(a)就可以查看lis里面值的个数
print(a.len()) # 不然就要使用类中的len方法才可以查看

# 输出
5
5

# -------------------------------------------------------------------------------------
# 扩展:也可以使用自定义的函数

class A:
def __init__(self, count):
self.count = count

def __square__(self):
value = self.count ** 2
return value

def square(count):
return A.__square__(count)

a = A(5)

print(square(a))

# 输出
25

__new__方法:实例化的时候会先执行__new__方法用来创建一个对象需要的空间

class A:
def __new__(cls, *args, **kwargs):
o = super().__new__(cls)
print(o) # 内存地址和 self 的内存地址一样
print('执行了__new__方法')
return o

def __init__(self):
print(self)
print('执行了__init__方法')

A() # 实例化对象

# 输出
<__main__.A object at 0x014E0970>
执行了__new__方法
<__main__.A object at 0x014E0970>
执行了__init__方法

__new__方法的设计模式:————>单例模式

一个类,从头到尾,只会创建一次 self 的空间

例如:我有一辆车(有且只有一辆),小红要拿去用,我就给她了,她拿去随便怎么改装,换个红色车漆,换蓝色车轮都可以。但是小明又过来找我要用车,那我就去把我的车给拿回来在给小明,也随小明随便改装。

class Car:
__attribute = None

def __new__(cls, *args, **kwargs):
if cls.__attribute is None: # 当第一次开空间的时候__attribute肯定是空的
# 所以就会开一个新的空间。并把__attribute给赋值,那么以后的都不是第一次了。
cls.__attribute = super().__new__(cls)
return cls.__attribute # 把新空间返回给self

def __init__(self, car_paint, cartwheel_colour):
self.car_paint = car_paint
self.cartwheel_colour = cartwheel_colour


xiao_hong = Car('红色的车漆', '蓝色的车轮')
print('小红的内存地址:', xiao_hong) # 他们的内存地址都是一样的
print(xiao_hong.car_paint) # 红色的车漆————>小红刚拿到的时候还是红色的
xiao_ming = Car('白色的车漆', '黑色的车轮')
print('小名的内存地址:', xiao_ming)
print(xiao_hong.car_paint) # 白色的车漆————>小明在拿过来,把颜色给改成白的了
print(xiao_ming.car_paint) # 白色的车漆————>小红的也变了,应为他们都是同一个车

# 输出
小红的内存地址: <__main__.Car object at 0x01A70A60>
红色的车漆
小名的内存地址: <__main__.Car object at 0x01A70A60>
白色的车漆
白色的车漆

__str____repr__方法:

str方法:帮助我们在打印或展示对象的时候更加直观的显示对象内容

1、在打印一个对象的时候,调用__str__方法

2、在 %s 拼接一个对象的时候,调用__str__方法

3、在str一个对象的时候,调用__str__方法

当打印一个对象的时候,希望这个对象显示的值是什么,那么你就必须在这个对象内部实现一个__str__ ,这样的话你就能做到,你在打印这个对象的时候你就能查看到他的内容是多少(查看的内容由你自己在 str 中定义),不然就只能答应一堆内存地址。

repr方法:是 str 的备胎(有str的时候打印str,没有就打印rper),同时 %r 和 repr 有合作关系

class User:
def __init__(self, name, age):
self.name = name
self.age = age

def __str__(self):
return self.name

def __repr__(self):
return self.age


Bob = User('鲍勃', '18')

print(Bob) # 现在就可以直接打印对象了,——不设置str方法,打印的就是是一堆内存地址,优先打印 str 方法

print('我的名字是%s' % Bob) # 在 %s 拼接一个对象的时候,调用__str__方法
print('我的年龄是%r' % Bob) # 在 %r 拼接一个对象的时候,调用__repr__方法

# 输出
鲍勃
我的名字是鲍勃
我的年龄是18

最新文章

  1. PHP错误以及异常处理
  2. JSBinding+Bridge.Net:框架代码与逻辑代码的关系
  3. SVM 简要推导过程
  4. [Python]爬虫v0.1
  5. CentOS 6.5部署安装Memcached
  6. 巧用jquery实现提交(submit)表单时候验证文本框是否为空
  7. Web Design:欧美人形剪影的404界面
  8. MATLAB GUI程序设计中使文本框接收多行输入的方法
  9. 安装apk文件报waiting for device 时解决办法
  10. 接口Interface
  11. 基于本地iso 搭建的本地yum源 安装部署openldap
  12. Tomcat部署发布JSP应用程序的三种方法 (转)
  13. uhttpd配置文件分析
  14. springmvc流程图
  15. CentOS下将php和mysql命令加入到环境变量中-简单
  16. 前端自动化构建工具webpack (一)之webpack安装 和 设置webpack.confi.js
  17. scrollview嵌套recyclerview卡顿现象
  18. PHP三种访问控制模式(public、protected、private)解析
  19. [19/04/20-星期六] Java的动态性_字节码操作(Javassist类库(jar包),assist:帮助、援助)
  20. 如何在Ubuntu 18.04上安装Go

热门文章

  1. for-in 语句
  2. python常见错误和异常
  3. IPFS是什么?IPFS与Filecoin有什么关系?
  4. PTA 带头结点的链式表操作集
  5. exe取消动态基址
  6. greenplum6.14、GPCC6.4安装详解
  7. HCL实验8:NAT搭建私有网络
  8. 黑马 - poi Excel
  9. https如何使用python+flask来实现
  10. mooc人大单元测试1