python 入门新手学习记录27 魔法方法 属性访问

一、类的定制

1、时间模块:time模块,用local time获取时间

  • 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。返回的是flot类型。产生时间戳方式的函数主要有time(),clock()等。
  • 格式化的时间字符串(Format String)
  • 结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)。返回struct_time的方法有gmtime(),localtime(),strptime()

localtime()返回的是一个元组,元组中有九个元素,我们只需要用到前面六个,分别是年月日时分秒,所以用检索元组的形式,分别定位,再做差,再将差值用字符串拼接的方式得到一个持续的时间。

class MyTimer():
    # 开始计时
     def start(self):
         self.start = t.localtime()
         print('计时开始...')
    # 停止计时
     def stop(self):
         self.stop = t.localtime()
         self._calc()
         print('计时结束...')
     def _calc(self):
         self.lasted = []
         self.prompt = '总共运行了'
         for index in range(6):
             self.lasted.append(self.stop[index] - self.start[index])
             self.prompt += str(self.lasted[index])
         print(self.prompt)

运行:
>>> t1 = MyTimer()
>>> t1.start()
计时开始...
>>> t1.stop()
总共运行了000007
计时结束...
>>> 

在这里插入图片描述
2、魔法方法__str__ 、__repr__,被打印的时候需要字符串的形式输出时直接打印A()

class A():
   def __str__(self):
      return '今天是个好天气'
class B():
   def __repr__(self):
      return '今天天气真好!'

运行:
>>> b = B()
>>> print(b)
今天天气真好!
>>> a = A()
>>> print(a)
今天是个好天气
>>> 
import time as t
class MyTimer():

   def __init__(self):
      self.begin = 0
      self.end = 0
      self.prompt = '未开始计时'
      self.lasted = []
      self.unit = ['年','月','天','小时','分钟','秒']

   def __str__(self):
      return self.prompt
   
   __repr__ = __str__
   
    # 开始计时
   def start(self):
         self.begin = t.localtime()
         print('计时开始...')
    # 停止计时
   def stop(self):
         self.end = t.localtime()
         self._calc()
         print('计时结束...')
   def _calc(self):
         self.lasted = []
         self.prompt = '总共运行了'
         for index in range(6):
             self.lasted.append(self.end[index] - self.begin[index])
             if self.lasted[index]:
                self.prompt += str(self.lasted[index])+self.unit[index]
         print(self.prompt)

==================== RESTART: C:\Users\1\Desktop\练习\11.py ====================
>>> t1 = MyTimer()
>>> t1.start()
计时开始...
>>> t1.stop()
总共运行了6秒
计时结束...
>>> 

二、属性访问(属性是特征,方法是功能)

1、属性的具体:一篇很好的文章:
https://www.cnblogs.com/gouguoqilinux/p/9194093.html

1、__getattr__(self,name)定义当用户试图获取一个不存在的属性时的行为

class Demo:
    def __getattr__(self,name):
        return "该属性不存在!"			#改写了getattr的方法,窥见getattr的用法
运行:
>>> demo = Demo()
>>> demo.x
'该属性不存在!'

2、__getattribute__(self,name),定义当该类的属性被访问时的行为

运行会先调用getattribute,当属性不存在时转而再调用getattr,若是赋值操作,则直接调用setattr

3、__setattr__(self,name),定义当一个属性被设置时的行为
4、__delattr__(self,name),定义当一个属性被删除时的行为

class Demo():
    
    def __getattr__(self,name):
        self.name ='i love here'
        return self.name
        

    def __setattr__(self,name,value):
        super().__setattr__(name,value)
        return self.name

>>> demo  =Demo()
>>> demo.x
'i love here'
>>> demo.x = 'ASD'
>>> demo.x
'ASD'
>>> 

方法二:
class Demo:
    def __getattr__(self,name):
        self.name = 'Iam here'
        return self.name

5、练习:
写一个类,定义一个矩形,具有长和宽两个属性,返回面积。如果为一个叫square的属性赋值,默认长和宽等于该边长

class Rectangle():
   def __init__(self,width = 0,height = 0):
      self.width = width
      self.height = height

   def __setattr__(self,name,value):
      if name == 'square':
         self.width = value
         self.height = value
      else :
         super().__setattr__(name,value)		#如果直接定义self.name = value,则会进入死循环
         										#因为__init__里面的赋值会自动给调用__seattr__
         										#而self.name = value,又会调用__seattr__,导致无限递归
         										#另一方法是 self.__dict__[name] = value
            
   def getArea(self):
      return self.width *self.height
   
运行:
>>> c = Rectangle(3,6)
>>> c.getArea()
18
>>> c.square = 10			#定义一个属性square被设置时,value=10
>>> c.getArea()
100
>>> c.width
10
>>> c.height
10
>>> 

再来巩固一下

class Count:
    def __init__(self):
        self.count = 0				#这个赋值操作会自动调用setattr操作

    def __setattr__(self,name,value):
        self.count +=1				#这个操作里面存在对count的运算,调用后self,count才真正设置,所以提示count不存在
运行:
>>> c = Count()
Traceback (most recent call last):
  File "C:\Users\1\Desktop\python\11.py", line 3, in __init__
    self.count = 0
  File "C:\Users\1\Desktop\python\11.py", line 6, in __setattr__
    self.count +=1
AttributeError: 'Count' object has no attribute 'count'

那么如何实现对类的属性的计数,检测对象有多少个属性

class Counter():
    def __init__(self):
        super().__setattr__('counter',0)

    def __setattr__(self,name,value):
        super().__setattr__('counter',self.counter+1)
        super().__setattr__(name,value)

    def __delattr__(self,name):
        super().__setattr__('counter',self.counter-1)
        super().__delattr__(name)


三、静态属性(标记,未学)

1、如何在继承的类中调用基类的属性——super()
2、继承的类是动态的该如何部署

为基类取别名,在继承时使用别名替代基类的名字

ABC=Baseclass

class A(ABC):
.....
3、类的静态属性

在类中直接定义的变量就是静态属性,静态属性调用的方法是,类名.属性

class C:
    count = 0			#静态属性
    def __init__(self):
        C.count =C.count +1		#静态属性的调用

    def getCount(self):
        return C.count


运行:
>>> c =C()
>>> c.getCount ()
1
>>> 
4、如何使用类的静态方法,静态方法属于特殊方法,在类名前面加上@staticmethod 静态方法不需要self参数,不会绑定到实例对象,实际就是节省开销
class C:
    @staticmethod
    def static(arg1,arg2,arg3):
        print(arg1,arg2,arg3)

    def nostatic(self):
        print('abcdefg')



>>> c=C()
>>> c2 = C()
>>> c.static
<function C.static at 0x0000021F739D1168>
>>> c2.static
<function C.static at 0x0000021F739D1168>		#c与c2的内存是同一个,节省了开销
>>> c.nostatic
<bound method C.nostatic of <__main__.C object at 0x0000021F739E0B88>>	
>>> c2.nostatic
<bound method C.nostatic of <__main__.C object at 0x0000021F73A2F688>>

>>> c.static(1,2,3)			#没有self参数
1 2 3
>>> 
发布了70 篇原创文章 · 获赞 5 · 访问量 3525

猜你喜欢

转载自blog.csdn.net/qq_42647903/article/details/102526796