两个类的装饰器,内置的魔术方法

类的装饰器

classmethod

  1. 什么时候用?

    1. 定义了一个方法,默认传self,但这个self没被使用,而且你在这个方法里用到了当前的类名,或者你准备使用这个类的内存空间中的名字

  2. 怎么定义?

    1. 装饰器怎么加?

      在被装饰的方法前写@classmethod

    2. 参数怎么改?

      将self改成cls,并在方法里面需要用类名的地方一致写上cls

     
    1 # classmethod  被装饰的方法会成为一个静态方法
    2  # class Goods:
    3  #     __discount = 0.8
    4  #     def __init__(self):
    5  #         self.__price = 5
    6  #         self.price = self.__price * self.__discount
    7  #     @classmethod   # 把一个对象绑定的方法 修改成一个 类方法
    8  #     def change_discount(cls,new_discount):
    9  #         cls.__discount = new_discount

     

  3. 怎么用?

    类名或者对象名皆可调用

    1  # Goods.change_discount(0.6)   # 类方法可以通过类名调用
    2  # apple = Goods()
    3  # print(apple.price)
    4  # apple.change_discount(0.5)  # 类方法可以通过对象名调用
    5  # apple2 = Goods()
    6  # print(apple2.price)

     

  4. 为什么用?有什么好处?

    在方法中仍然可以引用类中的静态变量;可以不用实例化对象,就直接用类名在外部调用这个方法

例子

 1  # import time
 2  # class Date:
 3  #     def __init__(self,year,month,day):
 4  #         self.year = year
 5  #         self.month = month
 6  #         self.day = day
 7  #     @classmethod
 8  #     def today(cls):
 9  #         struct_t = time.localtime()
10  #         date = cls(struct_t.tm_year,struct_t.tm_mon,struct_t.tm_mday)
11  #         return date
12  #
13  # date对象 = Date.today()
14  # print(date对象.year)
15  # print(date对象.month)
16  # print(date对象.day)

 

staticmethod

  1. 什么时候用

    本身是一个普通的函数,被移到类的内部执行,在方法内部既不会用到self变量,也不会用到cls变量

  2. 怎么定义

    在方法之前写上@staticmethod,别的不用改

    1  # class User:
    2  #     pass
    3  #     @staticmethod
    4  #     def login(a,b):      # 本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod装饰器就可以了
    5  #         print('登录的逻辑',a,b)

     

  3. 怎么用?由谁来调用

    对象和类都可以调用

    1  # obj = User()
    2  # User.login(1,2)
    3  # obj.login(3,4)

     

能定义在类中的内容

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

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

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

静态方法:是个啥都不带的普通函数 由对象\类调用

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

 
 1 class A:
 2      country = '中国'
 3      def func(self):
 4          print(self.__dict__)
 5      @classmethod
 6      def clas_func(cls):
 7          print(cls)
 8      @staticmethod
 9      def stat_func():
10          print('普通函数')
11      @property
12      def name(self):
13          return 'wahaha'

 

一些内置的魔术方法

__call__方法

类中有__call__方法的话就可被调用

对象()能不能运行就是callable判断的事

1  class A:
2      def __call__(self, *args, **kwargs):
3          print('-------')
4  # obj = A()
5  # print(callable(obj))
6  # obj()
7  # Flask框架的源码
8  # A()()    # 实例化对象在调用方法

 

__len__方法

len(对象)可不可用取决于这个类中有无__len__方法

 1  class Cls:
 2      def __init__(self,name):
 3          self.name = name
 4          self.students = []
 5      def __len__(self):
 6          return len(self.students)
 7  py22 = Cls('py22')
 8  py22.students.append('杜相玺')
 9  py22.students.append('庄博')
10  py22.students.append('大壮')
11  print(py22.__len__())
12  print(len(py22))

 

假如自己定义一个方法

 1 # class Pow:
 2 #     def __init__(self,n):
 3 #         self.n = n
 4 #     def __pow2__(self):
 5 #         return self.n ** 2
 6 
 7 # def pow2(obj):               # 这一步为了实现类似于len(list_1)的功能
 8 #     return obj.__pow2__()
 9 # obj = Pow(10)
10 # print(obj.__pow2__())

 

__str__方法和__repr__方法

  1. __str__方法:

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

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

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

     1 # class clas:
     2 #     def __init__(self):
     3 #         self.student = []
     4 #     def append(self,name):
     5 #         self.student.append(name)
     6 #     def __str__(self):
     7 #         return str(self.student)
     8 #
     9 # py22 = clas()
    10 # py22.append('大壮')
    11 # print(py22)
    12 # print(str(py22))
    13 # print('我们py22班 %s'%py22)
    14 # print(py22)
    15 # py22.append('大壮')
    16 # print(py22)

     

  2. __repr__方法

    1. 如果找不到__str__,就调用__repr__方法

    2. 用%r进行字符串拼接

    3. 用repr(对象)的时候

     1 # class clas:
     2 #     def __init__(self):
     3 #         self.student = []
     4 #     def append(self,name):
     5 #         self.student.append(name)
     6 #     def __repr__(self):
     7 #         return str(self.student)
     8 #     def __str__(self):
     9 #         return 'aaa'
    10 #
    11 # py22 = clas()
    12 # py22.append('大壮')
    13 # print(py22)
    14 # print(str(py22))
    15 # print('我们py22班 %s'%py22)
    16 # print('我们py22班 %r'%py22)
    17 # print(repr(py22))

     

__new__方法***

__new__方法是一种构造方法,其作用是在实例化的时候创建一块对象的空间,有一个指针可以指向类。其顺序在__init__之前

1 # class A:
2 #     def __new__(cls, *args, **kwargs):   # 构造方法
3 #         # o = super().__new__(cls)  #方法一
4 #         o = object.__new__(cls)     #方法二   两种方法皆可
5 #         print('执行new',o)
6 #         return o
7 #     def __init__(self):
8 #         print('执行init',self)
9 # A()

 

注意:在这个例子中self与o打印出来的结果一致,因为先调用__new__实例化以后会自动把这个实例传给self

设计模式—单例

总共有五种实现方法

方法一***(面试用):

 1 class Baby:
 2     __instance = None
 3     def __new__(cls, *args, **kwargs):
 4         if cls.__instance is None:
 5             cls.__instance = super().__new__(cls)
 6         return cls.__instance
 7     def __init__(self,cloth,pants):
 8         self.cloth = cloth
 9         self.pants = pants
10 b1 = Baby('红毛衣','绿皮裤')
11 print(b1.cloth)
12 b2 = Baby('白衬衫','黑豹纹')
13 print(b1.cloth)
14 print(b2.cloth)

 

方法二(平时用,简单方便):

1 # 在另一个模块中  单例.py
2 class Baby:
3     def __init__(self,cloth,pants):
4         self.cloth = cloth
5         self.pants = pants
6 
7 baby = Baby('红上衣','绿裤子')

 

1 # 在当前运行脚本下
2 from 单例 import baby
3 print(baby)
4 # 一个模块不会被重复导入,所以导入一次每次都是同一个地址

 

posted @ 2019-01-25 19:12  .如影随行  阅读(180)  评论(0编辑  收藏  举报