圆通快递 發表於 2020-2-11 14:06:00

Python进阶

<h2 id="装饰器">装饰器</h2>
<p>装饰器是Python中的一个重要概念,多用于在不修改原函数的基础上,为函数增加额外的功能。</p>
<h3 id="基础装饰器">基础装饰器</h3>
<p>例如小李给女朋友买了一款iPhone12作为生日礼物,手机原封未拆封。</p>
<pre><code class="language-python">def gift():
   print('iPhone12')

gift()   # 运行显示礼物信息
</code></pre>
<p>但还是觉得礼物太单薄,于是又买了一盒德芙巧克力,一支dior的口红,并找了个精美的礼品盒包装了一下,盒子里放满了泡沫球。</p>
<pre><code class="language-python">def gift():
   print('iPhone12')

def box(gift):
    print('='*5 + '礼物盒' + '='*5)
    print('一盒泡沫球')
    print('好多巧克力')
    print('一支dior口红')
    return gift

gift = box(gift)   # 将礼物包装后作为礼物
gift()# 显示礼物信息
</code></pre>
<p>运行后显示如下:</p>
<pre><code class="language-sh">=====礼物盒=====
一盒泡沫球
好多巧克力
一支dior口红
iPhone12
</code></pre>
<p>这个box便是一个装饰器,它的参数是一个函数对象,同数字、字符串、列表、字典等数据类型一样,函数和类也可以作为函数的参数使用,毕竟在Python里人人平等,一切皆对象。<br>
box在使用时依然返回了原来的gift,只是在拿到这个gift之前增加了两个额外的惊喜,然后我们把box作为gift使用即可。</p>
<p>装饰器本质上就是以函数作为参数,对函数做一些处理,并替换原函数的一种高阶函数。<br>
上例中,使用装饰器表示为如下。</p>
<pre><code class="language-python">def box(gift):   #以函数为参数的装饰器
    print('='*5 + '礼物盒' + '='*5)
    print('一盒泡沫球')
    print('好多巧克力')
    print('一支dior口红')
    return gift

@box      # 挂载装饰器,会自动替换原函数
def gift():
   print('iPhone12')

gift()   # 这里面得到的gift实际上是装饰后的gift即`box(gift)`
</code></pre>
<p>运行后显示和上例相同。</p>
<h3 id="处理函数参数">处理函数参数</h3>
<p>小李突然想到,买哪个颜色应该征询下女友的意见,也就是原来的gift应支持一个可供选择的颜色参数。</p>
<pre><code class="language-python">def gift(color):
    print(f'iPhone12{color}版')
</code></pre>
<p>作为一个细心的boyfriend,小李需要根据对应的手机颜色选择同样颜色的泡沫球,也就是需要能获取到,被装饰的gift函数的参数。<br>
这时候我们需要在盒子内部(box装饰器),重新准备一个新的礼物,根据颜色参数做不同的处理,然后根据颜色拿到指定的iPhone12礼物。</p>
<pre><code class="language-python">def box(gift):
    print('='*5 + '礼物盒' + '='*5)

    def new_gift(color):# 准备一个新的礼物,参数和原gift参数一致
      print(f'一盒{color}泡沫球')# 根据颜色准备泡沫球
      print('好多巧克力')
      print('一支dior口红')
      return gift(color)# 根据颜色拿到指定的iPhone12

    return new_gift   # 返回新礼物,新礼物调用时,增加一些惊喜,并返回原有礼物gift(color)的结果。

@box
def gift(color):
    print(f'iPhone12{color}版')

gift('红色')   # 实际上这里的gift是被box装饰后狸猫换太子的new_gift函数,而new_gift('红色'),返回原gift('红色')的结果。
</code></pre>
<p>在box内部为了根据参数做对应处理,我们新建了一个函数,函数内部也可以定义内部函数,内部函数new_gift可以获取并使用外部box函数的参数,如gift。<br>
为了能获取到原有函数gift的参数,我们需要建立一个傀儡函数new_gift,这个函数和原函数gift的参数一致、返回结果一致,即new_gift('红色')返回的就是gift('红色')。<br>
然后狸猫换太子,不再返回原来的gift函数对象,而是返回替换的new_gift函数对象。</p>
<p>运行后显示</p>
<pre><code class="language-sh">=====礼物盒=====
一盒红色泡沫球
好多巧克力
一支dior口红
iPhone12红色版
</code></pre>
<blockquote>
<p>注意:在装饰器box里,要返回一个函数对象,如上例中的<code>return gift</code>或本例中的<code>return new_gift</code>。而在傀儡函数new_gift中,为了和原函数gift结果一致,要返回原函数的调用结果即gift(color)。</p>
</blockquote>
<p>从普遍意义上讲,作为商家,为了装饰器box可以包装任何形式的礼物,无论礼物有什么参数都可以满足,这就要求我们的傀儡函数new_gift支持任意类型的参数即<code>def new_gift(*args, **kwargs)</code>。<br>
然后把无论什么参数<code>*args, **kwargs</code>交由原函数<code>gift(*args, **kwargs)</code>处理即可。<br>
修改后,我们便得到一个通用的装饰器,可以包装任何礼物。</p>
<pre><code class="language-python">def box(gift):
    print('='*5 + '礼物盒' + '='*5)

    def new_gift(*args, **kwargs):    # 接受任意数量的参数
      if args and len(args) &gt; 0:   # 由于参数不确定了,我们假设万一有参数,第一个参数是color参数
            color = args
            print(f'一盒{color}泡沫球')
      else:
            print(f'一盒泡沫球')

      print('好多巧克力')
      print('一支dior口红')
      result = gift(*args, **kwargs)# 如果我们需要对原函数的结果做出处理,可以先获取到结果
      # print(f'原函数结果{result}')    由于原函数gift没有return,这是其实是None
      return result# 返回原函数结果

    return new_gift

@box
def gift(color, pro=False):   # 新的礼物函数,两个参数,默认买12,万一女友要Pro,也可以
    if pro is True:
      print(f'iPhone12 Pro{color}版')
    else:
      print(f'iPhone12{color}版')

gift('海蓝色', pro=True)
</code></pre>
<p>这样,无论被装饰的函数有几个参数,box装饰器都可以正常处理。<br>
运行后显示如下。</p>
<pre><code class="language-sh">=====礼物盒=====
一盒海蓝色泡沫球
好多巧克力
一支dior口红
iPhone12 Pro海蓝色版
</code></pre>
<h3 id="带参装饰器">带参装饰器</h3>
<p>信心满满的小李觉得,在盒子上还可以做些文章,要根据女友的喜好选择不同形状的箱子,因此我们需要根据参数来定制我们的装饰器box,在盒子外面再加一层定制函数。</p>
<pre><code class="language-python">def custom_box(shape):   # 根据参数定制装饰器
    def box(gift):   # 装饰器函数
      print('='*5 + f'{shape}礼物盒' + '='*5)   # 根据形状定制
      # ...
    return box   # 返回装饰器函数
</code></pre>
<p>此时我们得到一个可以根据参数进行定制的装饰器函数custom_box,这个装饰器接收到参数后,传递给真实装饰器box,并返回定制后box装饰器函数。<br>
完整代码如下。</p>
<pre><code class="language-python">def custom_box(shape):   # 根据参数定制装饰器 =====================

    def box(gift):   # 实际的装饰器函数 ---------------------------
      print('='*5 + f'{shape}礼物盒' + '='*5)

      def new_gift(*args, **kwargs):   # 傀儡函数 ..............
            if args and len(args) &gt; 0:
                color = args
                print(f'一盒{color}泡沫球')
            else:
                print(f'一盒泡沫球')
            print('好多巧克力')
            print('一支dior口红')
            result = gift(*args, **kwargs)
            return result# 返回原函数结果 ......................

      return new_gift # 返回傀儡函数 ---------------------------

    return box   # 返回定制的装饰器 ===============================

@custom_box('心形')   # 使用可定制的装饰器
def gift(color, pro=False):
    if pro is True:
      print(f'iPhone12 Pro{color}版')
    else:
      print(f'iPhone12{color}版')

gift('海蓝色', pro=True)
</code></pre>
<blockquote>
<p>注意:装饰器在导入模块时立即计算的,即没调用<code>gift('海蓝色', pro=True)</code>之前就已经执行生成定制后的box。</p>
</blockquote>
<p>运行后,结果如下。</p>
<pre><code class="language-sh">=====心形礼物盒=====
一盒海蓝色泡沫球
好多巧克力
一支dior口红
iPhone12 Pro海蓝色版
</code></pre>
<h2 id="生成器和迭代器">生成器和迭代器</h2>
<p><img src="image3.png" alt="" loading="lazy"></p>
<h2 id="可迭代对象">可迭代对象</h2>
<p>实现了__iter__方法, __iter__方法返回一个迭代器</p>
<h2 id="迭代器">迭代器</h2>
<p>按标准的迭代协议实现__iter__和__next__方法,StopIteration结束</p>
<pre><code class="language-python">class A:
    start = 0
    def __iter__(self):
      return self

    def __next__(self):
      if self.start &gt; 10:
            raise StopIteration
      self.start += 1
      return self.start
</code></pre>
<h2 id="生成器">生成器</h2>
<p>内部实现了迭代器的一种函数,通过yield记录当前位置并返回一次迭代结果</p>
<pre><code class="language-python">def fib(max):
    n, a, b = 0, 0, 1
    while n &lt; max:
      print(b)
      a, b = b, a + b
      n = n + 1
    return 'done'
</code></pre>
<h2 id="列表推导式">列表推导式</h2>
<blockquote>
<p>推倒式:当我们对一批可迭代的数据(如列表或字典)进行提取或处理,最后要得到一个新的列表或字典时,推导式是一种非常简洁的表达方式。</p>
</blockquote>
<p>比如,有一批数据</p>
<pre><code class="language-python">data = [
    {'name': '张三', 'gender': 'male','age': 12},
    {'name': '李四', 'gender': 'female','age': 10},
    {'name': '王五', 'gender': 'male','age': 20},
    {'name': '赵六', 'gender': 'male','age': 11},
    {'name': '周七', 'gender': 'female','age': 16},
    {'name': '孙八', 'gender': 'male','age': 13},
]
</code></pre>
<p>我们想要把数据中的name都提取出来形成一个新的列表,一般的操作是这样的。</p>
<pre><code class="language-python">names = []# 定义一个空列表

for item in data:# 遍历数据
    name = item['name']# 提取每行中的name
    names.append(name)# 追加到列表中
</code></pre>
<p>如果用推导式的话,形式如下。</p>
<pre><code class="language-python">names = for item in data]   # 遍历data,提取每项中的name生成一个新列表
</code></pre>
<h3 id="数据处理">数据处理</h3>
<p>在提取数据时,我们还可以对每一项数据进行,处理,假设我们需要每个名称前加上'姓名: '这个字符串,可以这样。</p>
<pre><code class="language-python">names = ['姓名: '+item['name'] for item in data]
</code></pre>
<p><code>'姓名: '+item['name']</code> 就是每一项的数据</p>
<h3 id="数据筛选">数据筛选</h3>
<p>同样我们还可以对数据进行筛选,比如我们只要年龄大于12岁,后面可以使用if进行过滤</p>
<pre><code class="language-python">names = for item in data if item['age']&gt;12]
</code></pre>
<h3 id="多重循环">多重循环</h3>
<p>推导式还支持多重循环,比如</p>
<pre><code class="language-python">for x in range(1,5)
    if x &gt; 2
      for y in range(1,4)
            if y &lt; 3
                x*y
</code></pre>
<p>使用推导式表示如下</p>
<pre><code class="language-python">
</code></pre>
<h3 id="批量执行操作">批量执行操作</h3>
<p>由于推导式就是一种循环操作,我们也可以使用推导式来批量执行一些相似操作,比如:</p>
<pre><code class="language-python">def step1(driver):
    print('步骤1)

def step2(driver):
    print('步骤2)

def step3(driver):
    print('步骤3)
</code></pre>
<p>我们可以将函数名放到一个列表里,然后使用推导式循环执行</p>
<pre><code class="language-python">steps =    # 函数名列表

# 不需要变量接收,我们只需要它循环执行
</code></pre>
<h2 id="字典推导式">字典推导式</h2>
<p>当我们需要遍历一批数据最后得到一个字典时,同样可以使用字典推导式,如:</p>
<pre><code class="language-python">data = [
    {'name': '张三', 'gender': 'male','age': 12},
    {'name': '李四', 'gender': 'female','age': 10},
    {'name': '王五', 'gender': 'male','age': 20},
    {'name': '赵六', 'gender': 'male','age': 11},
    {'name': '周七', 'gender': 'female','age': 16},
    {'name': '孙八', 'gender': 'male','age': 13},
]
</code></pre>
<p>假设我们想得到一个<code>{'张三': 12, '李四': 10, ....}</code>这样的一个字典,使用字典推导式方式如下:</p>
<pre><code class="language-python">persons = {item['name']: item['age'] for item in data}
</code></pre>
<p>字典推导式同样支持if筛选等操作。</p>
<h2 id="生成器-1">生成器</h2>
<p>生成器实际上是一种包含初始数据和推导法则的对象,比如我们可以轻松的写出1w以内所有的奇数,原因是因为我只需要记住从1开始每次加2即可。<br>
生成器便是这样。对应大量的数据或者CSV/Excel文件中的数据,生成器可以大量的节省内存,比如csv.Reader(f)就是一个生成器,只存了当前位置和读取下一行数据的方法。<br>
当你需要遍历时,它再每次给你读取一行数据给你。<br>
如列表推导式的例子,</p>
<pre><code class="language-python">data = [
    {'name': '张三', 'gender': 'male','age': 12},
    {'name': '李四', 'gender': 'female','age': 10},
    {'name': '王五', 'gender': 'male','age': 20},
    {'name': '赵六', 'gender': 'male','age': 11},
    {'name': '周七', 'gender': 'female','age': 16},
    {'name': '孙八', 'gender': 'male','age': 13},
]
names = for item in data]
</code></pre>
<p>我们把列表的中括号改为小括号就得到一个生成器</p>
<pre><code class="language-python">names2 = (item['name'] for item in data)
</code></pre>
<blockquote>
<p>注意:生成器和推导式不同,其中的循环不是立即执行的,只用你遍历这个生成器时才会执行</p>
</blockquote>
<pre><code class="language-python">for name in names:# 遍历列表推导式生成的新列表
    print(name)

for name in names2:# 遍历一个生成器
    print(name)
</code></pre>
<p>两个打印结果是一样的,生成器更节省内存,只有遍历时才运行。</p>
<h2 id="魔术方法">魔术方法</h2>
<p>魔术方法是Python类中具有一定特殊作用的方法,这些方法名一般是<code>__魔术方法__</code>,即前后都带有两个下划线。</p>
<h3 id="常用魔术方法">常用魔术方法</h3>
<table>
<thead>
<tr>
<th>魔术方法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>__new__</code></td>
<td>创建类并返回这个类的实例</td>
</tr>
<tr>
<td><code>__init__</code></td>
<td>可理解为“构造函数”,在对象初始化的时候调用,使用传入的参数初始化该实例</td>
</tr>
<tr>
<td><code>__del__</code></td>
<td>可理解为“析构函数”,当一个对象进行垃圾回收时调用</td>
</tr>
<tr>
<td><code>__copy__</code></td>
<td>定义对类的实例调用 copy.copy() 获得对象的一个浅拷贝时所产生的行为</td>
</tr>
<tr>
<td><code>__deepcopy__</code></td>
<td>定义对类的实例调用 copy.deepcopy() 获得对象的一个深拷贝时所产生的行为</td>
</tr>
<tr>
<td><code>__str__</code></td>
<td>定义当前类的实例的文本显示内容</td>
</tr>
<tr>
<td><code>__repr__</code></td>
<td>定义当前类的实例的文本代表(实际)内容</td>
</tr>
<tr>
<td><code>__getattribute__</code></td>
<td>定义属性被访问时的行为</td>
</tr>
<tr>
<td><code>__getattr__</code></td>
<td>定义试图访问一个不存在的属性时的行为</td>
</tr>
<tr>
<td><code>__setattr__</code></td>
<td>定义对属性进行赋值和修改操作时的行为</td>
</tr>
<tr>
<td><code>__delattr__</code></td>
<td>定义删除属性时的行为</td>
</tr>
<tr>
<td><code>__len__</code></td>
<td>用于自定义容器类型,表示容器的长度</td>
</tr>
<tr>
<td><code>__getitem__</code></td>
<td>用于自定义容器类型,定义当某一项被访问时,使用 self 所产生的行为</td>
</tr>
<tr>
<td><code>__setitem__</code></td>
<td>用于自定义容器类型,定义执行 self=value 时产生的行为</td>
</tr>
<tr>
<td><code>__delitem__</code></td>
<td>用于自定义容器类型,定义一个项目被删除时的行为</td>
</tr>
<tr>
<td><code>__iter__</code></td>
<td>用于自定义容器类型,一个容器迭代器</td>
</tr>
<tr>
<td><code>__reversed__</code></td>
<td>用于自定义容器类型,定义当 reversed( ) 被调用时的行为</td>
</tr>
<tr>
<td><code>__contains__</code></td>
<td>用于自定义容器类型,定义调用 in 和 not in 来测试成员是否存在的时候所产生的行为</td>
</tr>
<tr>
<td><code>__missing__</code></td>
<td>用于自定义容器类型,定义在容器中找不到 key 时触发的行为</td>
</tr>
<tr>
<td><code>__eq__</code></td>
<td>定义相等符号“==”的行为</td>
</tr>
<tr>
<td><code>__ne__</code></td>
<td>定义不等符号“!=”的行为</td>
</tr>
<tr>
<td><code>__lt__</code></td>
<td>定义小于符号“&lt;”的行为</td>
</tr>
<tr>
<td><code>__gt__</code></td>
<td>定义大于符号“&gt;”的行为</td>
</tr>
<tr>
<td><code>__le__</code></td>
<td>定义小于等于符号“&lt;=”的行为</td>
</tr>
<tr>
<td><code>__ge__</code></td>
<td>定义大于等于符号“&gt;=”的行为</td>
</tr>
<tr>
<td><code>__add__</code></td>
<td>实现操作符“+”表示的加法</td>
</tr>
<tr>
<td><code>__sub__</code></td>
<td>实现操作符“-”表示的减法</td>
</tr>
<tr>
<td><code>__mul__</code></td>
<td>实现操作符“*”表示的乘法</td>
</tr>
<tr>
<td><code>__div__</code></td>
<td>实现操作符“/”表示的除法</td>
</tr>
<tr>
<td><code>__mod__</code></td>
<td>实现操作符“%”表示的取模(求余数)</td>
</tr>
<tr>
<td><code>__pow__</code></td>
<td>实现操作符“**”表示的指数操作</td>
</tr>
<tr>
<td><code>__and__</code></td>
<td>实现按位与操作</td>
</tr>
<tr>
<td><code>__or__</code></td>
<td>实现按位或操作</td>
</tr>
<tr>
<td><code>__xor__</code></td>
<td>实现按位异或操作</td>
</tr>
</tbody>
</table>
<h3 id="对象的创建及销毁">对象的创建及销毁</h3>
<ul>
<li><code>__new__</code>:用于控制创建对象</li>
<li><code>__init__</code>:用户控制创建对象后的初始化操作</li>
<li><code>__del__</code>:用于控制对象销毁时的操作</li>
</ul>
<p>例如,“单例模式”是一种常见的模式,单例模式要求某个类只能创建一个对象,即每次创建的都是同一个对象。我们可以使用<code>__new__</code>方法来控制对象(实例)的创建。</p>
<pre><code class="language-python">class Sun:
    __obj = None# 该属性用于存储类的唯一对象
   
    @classmethod
    def __new__(cls, *args, **kwargs):# __new__是类方法
      if cls.__obj is None:# 如果还没有创建对象
            cls.__obj = super().__new__(cls)# 创建一个对象
      return cls.__obj# 如果__obj已经创建了一个对象,则不创建新对象直接返回该对象
   
    def __init__(self):
      print('对象初始化')
      self.name = '太阳'# 初始化操作、比如为对象添加属性
      
    def __del__(self):
      print('噢,我要被销毁了')
      

sun1 = Sun()# 创建第一个对象
sun2 = Sun()# 尝试再创建一个对象

print('两个是同一个对象', sun1 is sun2) # 是同一个对象,即id(sun1) == id(sun2) 内存地址相同
</code></pre>
<p>运行后结果为:</p>
<pre><code class="language-sh">对象初始化
对象初始化
两个是同一个对象 True
噢,我要被销毁了
</code></pre>
<blockquote>
<p>注意:由于调用<code>__new__</code>后自动用<code>__init__</code>,虽然<code>__new__</code>始终返回同一个对象,仍可以用<code>__init__</code>通过初始化修改对象属性。</p>
</blockquote>
<h3 id="对象复制">对象复制</h3>
<p><code>__copy__</code>        :用于控制复制对象时操作<br>
<code>__deepcopy__</code>:用于控制深拷贝对象时的操作</p>
<p>深浅拷贝是Python中的一个知识点之一。当列表或字典中嵌套有其他列表或字典类型时,<strong>浅拷贝</strong>只拷贝子列表/字典的引用地址,<strong>深拷贝</strong>则将子列表/字典中所有的变量拷贝一遍。<br>
示例如下:</p>
<pre><code class="language-python">from copy import copy, deepcopy

l1 = ]

l2 = copy(l1)# 浅拷贝,对于列表中嵌套的可变类型 只拷贝引用地址
l3 = deepcopy(l1)# 深拷贝,对于列表中嵌套的可变类型 拷贝其中的所有变量

l1 = 'c1'# 修改l1中嵌套列表第一个的值
print(l1)
print(l2)# l2跟随改变
print(l3)# l3不受影响
</code></pre>
<p>使用魔术方法<code>__copy__</code>及<code>__deepcopy__</code>可以控制对象在copy()和deepcopy()操作时的行为。<br>
例如:</p>
<pre><code class="language-python">from copy import copy, deepcopy

class Planet:
    """行星"""

class Mercury(Planet):
    """水星"""
      
class Venus(Planet):
    """金星"""
      
class Earth(Planet):
    """地区"""

# ... 省略其他行星

class Sun:
    def __init__(self):
      self.name = '太阳'
      self.planets = []
      
    def add_planet(self, planet):
      self.planets.append(planet)
      
    def __copy__(self):
      new_sun = Sun()
      new_sun.name = self.name
      new_sun.planets = self.planets# copy后的新太阳和原太阳,共用所有的行星
      return new_sun
      
    def __deepcopy__(self, memodict={}):
      new_sun = Sun()
      new_sun.name = self.name
      for planet in self.planets:# 复制新太阳,把原太阳所有的行星拷贝一遍,拥有独立的行星
            new_sun.add_planet(planet.__class__())# 用行星的类创建一个新对象
      return new_sun
      

sun = Sun()
sun.add_planet(Mercury())
sun.add_planet(Venus())
sun.add_planet(Earth())

new_sun1 = copy(sun)
print(new_sun1.planets is sun.planets)# 是同一个水星

new_sun2 = deepcopy(sun)
print(new_sun2.planets is not sun.planets)# 不是同一个水星
</code></pre>
<p>显示结果如下:</p>
<pre><code class="language-sh">True
True
</code></pre>
<h3 id="对象及类型信息">对象及类型信息</h3>
<p>Python3中,str()和repr()都是将对象转为字符串形式,不同的是:</p>
<ul>
<li>str():是显示文本,更适合人类查看</li>
<li>repr(): 对象表示,更清晰的显示其类型及实际格式<br>
例如:</li>
</ul>
<pre><code class="language-python">a = '''
hello
world
'''
print(a)# 如果a不是字符串类型 print(a)相当于print(str(a))
print(repr(a))
</code></pre>
<p>显示结果为:</p>
<pre><code class="language-sh">
hello
world

'\nhello\nworld\n'
</code></pre>
<p>使用<code>repr()</code>我们可以更清楚,a是一个字符串(前后有单引号),且包含了3个换行。</p>
<p>str及repr的默认使用场景为:</p>
<ul>
<li>调用str(obj)方法时:调用对象的<code>__str__</code>方法(如果没有调用父类,如object类的<code>__str__</code>方法)</li>
<li>调用repr(obj)方法时:调用对象的<code>__repr__</code>方法(如果没有调用父类,如object类的<code>__repr__</code>方法)</li>
<li>print(obj)时,如果对象有<code>__str__</code>方法则调用其 <code>__str__</code>方法,否则尝试调用其<code>__repr__</code>方法,如果没有按顺序调用父类<code>__str__</code>或<code>__repr__</code>方法</li>
<li>Python交互命令行中,直接输入<code>&gt;&gt;&gt; obj</code>,回车时,调用对象的<code>__repr__</code>方法(如果没有调用父类,如object类的<code>__repr__</code>方法)</li>
</ul>
<p>当定义一个类时,我们可以使用<code>__str__</code>及<code>__repr__</code>方法,在打印或调试时使的对象更清晰。</p>
<pre><code class="language-python">class Sun:
    """太阳"""
    def __init__(self):
      self.name = '太阳'
   
    def __str__(self):# 定义 对象转为 字符串形式的值
      return self.name
   
    def __repr__(self):# 定义对象实际代表形式
      return "&lt;Sun %s&gt;" % self.name

sun = Sun()

print('对象文本形式', sun)# print(sun) 相当于print(str(sun)) str(obj) 相当于调用 obj.__str__()
print('对象表示形式', repr(sun))# # repr(obj) 相当于调用 obj.__repr__()
</code></pre>
<p>运行后结果如下:</p>
<pre><code class="language-sh">对象文本形式 太阳
对象表示形式 &lt;Sun 太阳&gt;
</code></pre>
<p>如果想查看对象其他属性,或者类相关属性,参考如下:</p>
<pre><code class="language-python"># 获取对象所有属性及方法
print(dir(sun))

# 查看类相关属性
print('对象所属类', sun.__class__,
      '类名', sun.__class__.__name__,
      '类注释', sun.__class__.__doc__,
      '类的父类', sun.__class__.__base__,
      '类的所有父类', sun.__class__.__bases__,
      )
</code></pre>
<p>运行后结果如下:</p>
<pre><code class="language-sh">['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
对象所属类 &lt;class '__main__.Sun'&gt; 类名 Sun 类注释 太阳 类的父类 &lt;class 'object'&gt; 类的所有父类 (&lt;class 'object'&gt;,)
</code></pre><br><br>
来源:https://www.cnblogs.com/superhin/p/12294878.html
頁: [1]
查看完整版本: Python进阶