Python Ecosystem之Python篇章二

高亮颜色说明:突出重点
个人觉得,:待核准个人观点是否有误

本篇博客涵盖以下内容:

  • 函数

zip([iterable, …])的用法

  zip()将多个可迭代对象中的元素依次相连打包为tuple, 然后返回由这些tuple组成的一个’zip对象’; 假设某个可迭代对象中的元素数量最少, 有n_in个, 则该’zip对象’中的tuple数量也就为n_in个;

list_1 = [1,2,3]
list_2 = [4,5,6,7,8]
zipped_1 = zip(list_1,list_2)
>>> list(zipped_1)  # list()仅仅是将'zip对象'转换成list形式, 'zip对象'中的元素仍然保持其原始的形式
>>> [(1, 4), (2, 5), (3, 6)]

  zip(*)将单个可迭代对象中的元素的元素依次相连打包为tuple, 然后返回由这些tuple组成的一个’zip对象’; 假设可迭代对象中的某个元素的元素数量最少, 有n_in_in个, 则该’zip对象’中的tuple数量也就为n_in_in个;

string_1 = ['flower','flow','flight']
for s in zip(*string_1):  # 由于'*string_1'拆散了string_1, string_1包含有3个元素,因此zip(*)就相当于zip()作用在3个可迭代对象上;
    print(s)
>>> 
('f', 'f', 'f')
('l', 'l', 'l')
('o', 'o', 'i')
('w', 'w', 'g')

示例tuple(map(list, zip(*map_results)))

  综合示例:

string_2=([torch.ones(10,4), torch.zeros(12,4)], [dict(img_shape=(800,600,3)), dict(img_shape=(800,600,3))])
>>> tuple(map(list, zip(*map(lambda x:x, string_1))))
>>> ([torch.zeros(10,4), dict(img_shape=(800,600,3))], [torch.zeros(12,4), dict(img_shape=(800,600,3))])

str_1, str_2, str_3='flower','flow','flight'  # 例如, str_1的元素是'f','l','o','w','e','r'这一个个单字符;
string_1=(str_1, str_2, str_3)  # string_1的元素是str_1, str_2, str_3这一个个字符;
map_results=map(lambda x:x, string_1)  # 对序列string_1执行函数pfunc, 将pfunc(string_1)的结果作为一个'map对象'返回
>>> map_results
>>> <map at 0x7fed07b297c0>
# 博主这里将str_1, str_2, str_3也称呼为map_results中的元素
zip_obj_1=zip(*map_results)  # zip(*)将单个可迭代对象中的元素的元素依次相连打包为tuple, 然后返回由这些tuple组成的一个'zip对象'; 假设可迭代对象中的某个元素的元素数量最少, 有n_in_in个, 则该'zip对象'中的tuple数量也就为n_in_in个;
>>> zip_obj_1
>>> <zip at 0x7fed0e1befc0>
map_obj_2=map(list, zip_obj_1)  # 将'zip对象'中的元素逐个转换为list形式, 然后返回由这些list组成的一个'map对象';
>>> map_obj_2
>>> <map at 0x7fed07b00fa0>
>>> tuple(map_obj_2)
>>> (['f', 'f', 'f'], ['l', 'l', 'l'], ['o', 'o', 'i'], ['w', 'w', 'g'])

# 注意下,比较list(zip_obj_1)与tuple(map(list, zip_obj_1))之间的不同
string_1 = ['flower','flow','flight']
map_results=map(lambda x:x, string_1)
zip_obj_1=zip(*map_results)
>>> list(zip_obj_1)  # list()仅仅是将'zip对象'转换成list形式, 'zip对象'中的元素仍然保持其原始的形式
>>> [('f', 'f', 'f'), ('l', 'l', 'l'), ('o', 'o', 'i'), ('w', 'w', 'g')]

  mmdetection/mmdet/core/utils/misc.py

# mmdetection/mmdet/core/utils/misc.py
def multi_apply(func, *args, **kwargs):
    """Apply function to a list of arguments.

    Note:
        This function applies the ``func`` to multiple inputs and
        map the multiple outputs of the ``func`` into different
        list. Each list contains the same type of outputs corresponding
        to different inputs.

    Args:
        func (Function): A function that will be applied to a list of
            arguments

    Returns:
        tuple(list): A tuple containing multiple list, each list contains \
            a kind of returned results by the function
    """
    pfunc = partial(func, **kwargs) if kwargs else func
    map_results = map(pfunc, *args)  # 对序列*args执行函数pfunc, 将pfunc(*args)的结果作为一个'map对象'返回
    return tuple(map(list, zip(*map_results)))

map(func, iterable, …)和reduce(func, iterable, …)的用法

map/reduce - 廖雪峰的官方网站

函数定义,传参,调用

***精选_Python编程核心内容 ---- Function(函数) - jack_Meng - 博客园 20180312
  在Python中,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

def  func_01(a, b, c=0, *args, **kw):
    print('a=', a, 'b=', b, 'c=', c, 'args=', args, 'kw=', kw)

def  func_02(a, b, c=0, *, d, **kw):
    print('a=', a, 'b=', b, 'c=', c, 'd=', d, 'kw=', kw)

args_01 = (1,2,3,4)
kw_01 = {'d':88, 'x':'#'}
args_02 = (1,2,3)
kw_02 = {'d':88, 'x':'#'}
func_01(*args_01, **kw_01)
# a= 1 b= 2 c= 3 args= (4,) kw= {'d': 88, 'x': '#'}
func_02(*args_02, **kw_02)
# a= 1 b= 2 c= 3 d= 88 kw= {'x': '#'}
print('\nfinish!')

装饰器

*** 精选_python的装饰器 - 我是小随 - 博客园 20180121

.apply()

super(__class__, ins).func(*args, **kwargs)

20201002记:
  super语法如下:
super(__class__, ins).func(*args,**kwargs)

  • __calss__指定需要继承 指定的类__calss__ 的父类;这一点尤其需要注意

  • ins:代表实例对象其本身,一般都是self;

  • func:是要继承的方法,同时传递该方法需要的参数(不需要再传递cls或self形参,直接传递必要的其他参数);

  在python3中,也可以省略掉super中的两个参数,即代表继承当前实例对象的所有父类的方法(如果存在多重继承的话):
super().func(*args,**kwargs)

  除了使用super继续执行继承外,还有一种更直接的继承的方法:直接通过父类名称来调用父类的方法,但不建议直接使用父类名称进行调用

全面理解python中self的用法 - JanWong - 博客园20180724
*** Python类和实例_weixin_41677555的博客 20180419 -> 七

>>> help(super)
Help on class super in module builtins:
# super是一个类,调用super()的本质是调用super类的构造方法来创建super对象。
class super(object)
# 使用super()最常用的做法就是不给super()传入任何参数,此时默认__class__指定继承当前类的第一个父类;
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 # 通过super对象既可以调用指定类的第一个父类的实例方法,也可以调用指定类的第一个父类的类方法;
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)  # 在调用父类的实例方法时, 程序会自动完成第一个参数self的自动绑定
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)  # 在调用父类的类方法时, 程序会自动完成第一个参数cls的自动绑定
 |  
 |  Methods defined here:
 |  
 |  __get__(self, instance, owner, /)
 |      Return an attribute of instance, which is of type owner.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __self__
 |      the instance invoking super(); may be None
 |  
 |  __self_class__
 |      the type of the instance invoking super(); may be None
 |  
 |  __thisclass__
 |      the class invoking super()

类的定义/继承/重写/实例化

Python基础学习之路(七) ------ 类/继承/重写_千喜-CSDN博客 20190719

多层继承, 多重继承

  • 多层继承:子类创建的实例可调用所有层级父类的属性和方法;
  • 多重继承:通常将和子类更相关的父类放在更左侧。创建的实例在调用属性和方法时,会依据子类的MRO顺序,会先在排在前面的父类中找,找不到才会去排在后面的父类找,可理解为"就近原则";

多继承时函数的执行顺序

print(class_name_1.__mro__)  # 可以打印输出子类class_name_1所继承的父类的MRO顺序

  多继承时, 类的初始化方法的执行顺序是按照MRO原则顺序执行的,参见*** Python类和实例_weixin_41677555的博客 20180419 -> 七
  有时子类覆盖了父类的方法,但仍需要使用父类方法时,可以使用super(这是一个类,不是一个函数),*** Python类和实例_weixin_41677555的博客 20180419 -> 七
  注:另可参考python进阶(八)_python高级语法_多继承_雎智明智 20190419 -> 总结,该博客的作者对super的理解可能不是很深入,但是该博客中示例程序的运行结果有助于理解多重继承时函数的执行顺序;

子类继承于多个父类时, 如何正确处理该子类的初始化?

20201002记:
继承多个父类时引发的BUG与修复方法 20191008

  若子类继承于多个父类,那么子类对象在创建时会按照子类定义中的父类继承顺序调用父类的构造方法( init());此时,如何正确处理该子类的初始化才能完成该子类的实例化操作呢?
  答案是在该子类中定义自己的构造方法,即重写父类的构造方法,但必须遵循Python的规则:“若在子类中重写父类的构造方法,那么子类的构造方法必须调用父类的构造方法!”

  python中子类构造方法调用父类构造方法的方式有两种:

  • 通过未绑定方法直接逐个调用多个父类的构造方法;
  • 通过super()方法创建super对象来调用第一个父类的构造方法;

  需要注意的是:”当子类继承于多个父类时,即多继承时,super对象只可用于调用第一个父类中的方法,其余父类中的方法只能使用未绑定的方式调用。“

# python_20201002_note01.py

class People:
    def __init__(self, color):
        self.color = color
        print("People.__init__()被调用了")

    def human(self):
        print("此人种为: %s" % self.color)


class Chinese:
    def __init__(self, country, city):
        self.country = country
        self.city = city
        print("Chinese.__init__()被调用了")

    def infor(self):
        print("我是中国人, 我的国籍是: %s, 所在城市为: %s" % (self.country, self.city))


class Student:
    def __init__(self, school):
        self.school = school
        print("Student.__init__()被调用了")


flag = '2_4'  # {'1_1', '1_2'}, {'2_1', '2_2', '2_3', '2_4'}
if flag == '1_1':
    class Man(People, Chinese):
        pass  # 只做演示, 无需添加详细代码


    p = Man("黄种人")  # 一个参数, 只能调用父类People的构造函数来初始化color变量, 而无法调用父类Chinese的构造函数来初始化country和city变量
    p.human()  # 由于color被初始化, 所以调用human()时, 没有错误
    p.infor()  # 由于country和city未被初始化, 所以调用infor()时, 会报错:AttributeError: 'Man' object has no attribute 'country'

elif flag == '1_2':
    class Man(Chinese, People):
        pass  # 只做演示, 无需添加详细代码


    p = Man("中国", "上海")  # 只能调用父类Chinese的构造函数来初始化country和city变量, 而无法调用父类People的构造函数来初始化color变量
    p.infor()  # 由于country和city被初始化, 所以调用infor()时, 没有错误
    p.human()  # 由于color未被初始化, 所以调用human()时, 会报错:AttributeError: 'Man' object has no attribute 'color'

elif flag == '2_1':
    class Man(People, Chinese):
        # 方法一:通过未绑定方法直接逐个调用多个父类的构造方法
        def __init__(self, color, country, city):
            print("---调用父类People的构造方法---")
            People.__init__(self, color)
            print("---调用父类Chinese的构造方法---")
            Chinese.__init__(self, country, city)


    p = Man("黄种人", "中国", "上海")
    p.human()
    p.infor()

elif flag == '2_2':
    class Man(People, Chinese):
        # 方法二:通过super()方法创建super对象来调用第一个父类的构造方法
        def __init__(self, color, country, city):
            print("---调用父类People的构造方法---")
            # super().__init__(color)  # 不给super()传入任何参数时,则默认__class__指定继承当前类的第一个父类; 此行代码与下一行代码等效;
            super(Man, self).__init__(color)  # 此处指定继承Man的第一个父类People的__init__()方法; 原博客此处有误;
            print("---调用父类Chinese的构造方法---")
            # 多继承时,super对象只可用于调用第一个父类中的方法; 因此不能再写super(Man, self).__init__(country, city);
            Chinese.__init__(self, country, city)


    p = Man("黄种人", "中国", "上海")
    p.human()
    p.infor()

elif flag == '2_3':
    class Man(People, Chinese):
        def __init__(self, color, country, city):
            print("---调用父类People的构造方法---")
            super(Man, self).__init__(color)
            print("---调用父类Chinese的构造方法---")
            Chinese.__init__(self, country, city)
            print("Man.__init__()被调用了")


    class Boy(Student, Man):
        # 方法二:通过super()方法创建super对象来调用第一个父类的构造方法
        def __init__(self, school, color, country, city):
            print('类Boy所继承的父类的MRO顺序:', Boy.__mro__)
            print('super(Boy, self)的值:', super(Boy, self), '\nsuper()的值:', super())
            super(Boy, self).__init__(school)  # 此处指定继承Boy的第一个父类Student的__init__()方法;
            # Man.__init__(self, color, country, city)  # 此行代码可以实现下面两行代码的功能
            super(Man, self).__init__(color)  # 此处指定继承Man的第一个父类People的__init__()方法;
            Chinese.__init__(self, country, city)


    p = Boy("高中", "黄种人", "中国", "上海")
    p.human()
    p.infor()

elif flag == '2_4':
    class PrintText:
        def print_text(self):
            print("PrintText.print_text()被调用了")

    class ChineseP(PrintText, Chinese):  # 类PrintText中无构造方法, 此时即便将PrintText放在更左侧, 但在ChineseP.__mro__结果中PrintText仍然排在Chinese后面
        def __init__(self, country, city):
            print('类ChineseP所继承的父类的MRO顺序:', ChineseP.__mro__)
            # ChineseP所继承的父类的MRO顺序: (<class '__main__.ChineseP'>, <class '__main__.PrintText'>, <class '__main__.Chinese'>, <class 'object'>)
            print("---调用父类Chinese的构造方法---")
            # 不给super()传入任何参数时,则默认__class__指定继承当前类的第一个父类;
            super().__init__(country, city)
            print("ChineseP.__init__()被调用了")


    p = ChineseP("中国", "上海")
    p.print_text()
    p.infor()

类方法, 实例方法, 静态方法

*** Python类和实例_weixin_41677555的博客 20180419 -> 四

  • 类方法
    类方法是类自身定义的方法,在定义的方法前使用语法糖@calssmethod,并且方法的第一个参数必须为cls;
    类方法可以被类自身调用,也可被实例调用;
    一般情况下,类方法在类中进行修改和添加,但也可以使用动态的方式来增加或修改类方法;
  • 实例方法
    实例方法是在类中使用self关键字创建的;
    实例方法只能通过实例调用,正常情况下类是不能调用实例方法的;
    同样地,实例方法也可以动态添加,但分两种情况:一种是动态地给类增加实例方法,则所有由该类创建的实例都能调用;另一种是只为当前实例动态增加方法,则该方法只有当前实例有效,其他实例无法调用;
  • 静态方法
    静态方法在类中创建时使用@staticmethod语法糖;
    对于静态方法,类和实例都可以调用,但动态增加的静态方法只有类才能调用;
# python_20201002_note01.py

class ClassName1:  # 该行语句与class ClassName1(object)等效; object是所有类的父类, 我们将其称为根类(可理解为类的始祖);
    """docstring"""

    cls_var_1 = 1.01  # 创建一个类变量(class variable); 一般, 如果定义了初始化方法, 就直接在初始化方法中创建类的属性, 而无需创建一个类变量;

    def __init__(self, fld_1, fld_n, *args, **kwargs):  # 定义初始化方法
        self.fld_1 = fld_1  # 创建类的属性
        self.fld_n = fld_n

    def ins_method_1(self, *args, **kwargs):  # 定义实例方法(instance method)
        pass  # 实例方法是指类中参数带self的函数, 是类方法的一种形式;

    @classmethod
    def cls_method_1(cls, *args, **kwargs):  # 定义类方法(class method)
        pass

    @staticmethod
    def cls_method_1(*args, **kwargs):  # 定义静态方法(static method)
        pass


class ClassName2(ClassName1):

    def __init__(self, fld_31, fld_32=1024, *args, **kwargs):
        # 针对上一行代码的注释:传入的参数中必须得有fld_31参数, 否则会报错;
        # 如果传入的参数中包含fld_32参数, 则会从传入的参数中索引出fld_32的值; 如果不包含的话, 则fld_32采用默认值1024;
        # 传入的参数中除去fld_31, fld_32之外的剩余参数, 将存入args, kwargs中;
        super(ClassName2, self).__init__(
            fld_21=0,  # 此几行新增的参数会连同args, kwargs一起传入ClassName1的构造函数中
            fld_22=fld_31,  # 利用fld_31的值给参数fld_22赋值
            fld_23=fld_32,  # 利用fld_32的值给参数fld_23赋值
            *args,
            **kwargs)
        self.fld_2 = fld_31

@abstractmethod的用法

  抽象方法:
  抽象方法表示基类的一个方法,没有实现,所以基类不能实例化,子类实现了该抽象方法才能被实例化。
  Python的abc模块提供了@abstractmethod装饰器实现抽象方法,下面以Python3的abc模块举例。

  @abstractmethod:
  见链接中的代码,基类Foo的fun方法被@abstractmethod装饰了,所以Foo不能被实例化;子类SubA没有实现基类的fun方法也不能被实例化;子类SubB实现了基类的抽象方法fun所以能实例化。

# Python3.0到Python3.3的实现方法
from abc import abstractmethod, ABCMeta

class Bar(metaclass=ABCMeta):
    @abstractmethod
    def fun(self):
        '''please Implement in subclass'''


class SubBar(Bar):
    def fun(self):
        print('fun in SubBar')


b = SubBar()
b.fun()

判断 Python 对象是否为可调用的函数

20230411记:

判断 Python 对象是否为可调用的函数,有三种方法:

1、使用内置的`callable`函数
callable(func) 用于检查对象是否可调用,
返回True也可能调用失败,但是返回False一定不可调用

2、判断对象类型是否是`FunctionType`
from types import FunctionType
type(func) is FunctionType
或者
isinstance(func, FunctionType)

3、判断对象是否实现`__call__`方法
hasattr(func, '__call__')

类属性, 实例属性

Python类和实例_weixin_41677555的博客-CSDN博客 -> 三
  实例属性是当前实例所私有的,仅可以被当前实例调用,实例属性可以来自于类的实例化,也可以在无其他限制条件的前提下由实例对象本身进行添加;

  由类创造的属性,既可以被该类调用和修改,同时所有该类的实例也都可以对该属性进行引用和修改;但若实例新增了和类属性同名的属性,则对于该实例而言,该实例所属类的类属性被暂时覆盖;若从该实例中删除了该同名属性的话,该实例同样可以调用该实例所属类的该属性;

class St(object):
    name='Lia'

s1=St()
print(s1.name)  # 由于该实例无name属性,引用类属性
s1.name='Mark'  # 实例属性覆盖类属性
s1.age=18  # 给实例对象本身添加新的实例属性
print(St.name)  # 类属性
print(s1.name)  # 实例属性
del s1.name  # 删除实例属性
print(s1.name) # 删除实例属性仍然可以引用类属性
---------------------------------------
# 结果输出:
Lia
Lia
Mark
Lia

Python内置函数

Python内置函数大全_Python热爱者的博客-CSDN博客 20211222

使用内置函数和魔术方法获取类属性/类方法信息

*** Python类和实例_weixin_41677555的博客 20180419 -> 五

魔术方法和定制类

  在Python中,以双下划线’__'开头和结尾的内置方法被称为魔法方法;
*** Python类和实例_weixin_41677555的博客 20180419 -> 八

__dict__属性 (转载,订正)

Python __dict__属性详解 - //偏执 20180529

1.无处不在的__dict__属性

  首先看一下的__dict__属性和类对象的__dict__属性

# -*- coding: utf-8 -*-


class A(object):
    """
    Class A.
    """

    a = 0
    b = 1

    def __init__(self):
        self.a = 2
        self.b = 3

    def test(self):
        print 'a normal func.'

    @staticmethod
    def static_test(self):
        print 'a static func.'

    @classmethod
    def class_test(self):
        print 'a calss func.'


obj = A()
print A.__dict__
print obj.__dict__

  运行结果如下:

{'a': 0, '__module__': '__main__', 'b': 1, 'class_test': <classmethod object at 0x00000000021882E8>, '__dict__': <attribute '__dict__' of 'A' objects>, '__init__': <function __init__ at 0x00000000023A5BA8>, 'test': <function test at 0x00000000023A5C18>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': '\n    Class A.\n    ', 'static_test': <staticmethod object at 0x00000000021881C8>}
{'a': 2, 'b': 3}

  由此可见,

  1. 类变量、实例方法(普通函数)、静态方法、类方法、以及一些内置的属性都是放在的__dict__里的;
  2. 类对象的__dict__中存储的是 字段 (fields),即self.xxx。

2.Python里什么没有__dict__属性

  虽然说一切皆对象,但对象也有不同,Python中一些内置的数据类型是没有__dict__属性的,如下:

num = 3
ll = []
dd = {}
print num.__dict__
print ll.__dict__
print dd.__dict__

  运行结果如下:

Traceback (most recent call last):
  File "f:\python\test.py", line 54, in <module>
    print num.__dict__
AttributeError: 'int' object has no attribute '__dict__'

Traceback (most recent call last):
  File "f:\python\test.py", line 55, in <module>
    print ll.__dict__
AttributeError: 'list' object has no attribute '__dict__'

Traceback (most recent call last):
  File "f:\python\test.py", line 56, in <module>
    print dd.__dict__
AttributeError: 'dict' object has no attribute '__dict__'

  int, list, dict等这些常用的数据类型是没有__dict__属性的,其实这是可预料的,就算给了它们__dict__属性也没啥用,毕竟它们只是用来做数据容器的。

3.发生继承时候的__dict__属性

  子类有自己的__dict__,父类也有自己的__dict__,两者的__dict__互不影响。

# -*- coding: utf-8 -*-


class Parent(object):
    a = 0
    b = 1
    d = 8

    def __init__(self):
        self.a = 2
        self.b = 3

    def p_test(self):
        pass


class Child(Parent):
    a = 4
    b = 5
    d = 9

    def __init__(self):
        super(Child, self).__init__()
        self.a = 6
        # self.b = 7
        self.e = 7

    def c_test(self):
        pass


p = Parent()
c = Child()
print(Parent.__dict__)
print(Child.__dict__)
print(p.__dict__)
print(c.__dict__)

  运行结果如下:

{'__module__': '__main__', 'a': 0, 'b': 1, 'd': 8, '__init__': <function Parent.__init__ at 0x000002C1C2AEF828>, 'p_test': <function Parent.p_test at 0x000002C1C2AEF438>, '__dict__': <attribute '__dict__' of 'Parent' objects>, '__weakref__': <attribute '__weakref__' of 'Parent' objects>, '__doc__': None}
{'__module__': '__main__', 'a': 4, 'b': 5, 'd': 9, '__init__': <function Child.__init__ at 0x000002C1C2AEFC18>, 'c_test': <function Child.c_test at 0x000002C1C2AEF048>, '__doc__': None}
{'a': 2, 'b': 3}
{'a': 6, 'b': 3, 'e': 7}

  由此可见,

  1. 无论是父类还是子类,每个类的类变量、函数名都放在自己的__dict__中;的__dict__属性是不包含 字段 (fields) 的
  2. 类对象的__dict__中存储的是 字段 (fields),即self.xxx

__dict__属性小结

  1. 内置的数据类型没有__dict__属性;
  2. 每个类有自己的__dict__属性,就算存着继承关系,父类的__dict__ 并不会影响子类的__dict__;的__dict__属性是不包含 字段 (fields) 的
  3. 类对象也有自己的__dict__属性, 存储self.xxx 信息,父子类对象公用__dict__;类对象的__dict__中存储的是 字段 (fields),即self.xxx

__attr__属性

__all__变量

import module_a  # 导入模块module_a
from module_b import *  # 导入模块module_b的所有内容

  __init__.py脚本文件中的__all__,用于在该模块被导入时对该模块被导入的内容进行限制。若在该模块的__init__.py中定义了__all__属性,则只有__all__内指定的类、属性、方法可以被导入;若没定义,则该模块内的所有类、公有属性,方法都可以被导入。
  详参:python中模块的__all__详细使用 - 停滞的时光 - 博客园 20190320


  Python中,一个py文件就是一个模块。
  __all__变量,是为了限制或者指定当前模块中哪些属性(e.g. 类、函数、全局变量)能够被导入到其它模块中。

  1. 普通模块中添加__all__变量

  例如,

# temp_001.py
__all__=["test1_a"]

def test1_a():
	print('----test1_a-----')

def test1_b():
	print('----test1_b----')
# temp_003.py
from temp_001 import *

def test3():
	test1_a()
	# test1_b()

  如果在模块temp_001.py中设置了__all__变量,则只能是__all__变量指定的那些属性可以被导入到其它模块中;如果在模块temp_001.py中没有设置__all__变量,则模块temp_001.py中的所有属性都可以被可以导入其它模块中,当然私有属性应该除外。

  1. 包的__init__.py文件中添加__all__变量

  如果在包的__init__.py文件中设置了__all__变量,

# file_001/pkg_001/__init__.py
__all__=["temp_001", "temp_002"]
# temp_003.py
from file_001.pkg_001 import *  # 导入"temp_001", "temp_002"这两个模块

def test3():
	pass

  如果在包的__init__.py文件中没有设置__all__变量,

# file_001/pkg_001/__init__.py
# temp_003.py
import file_001.pkg_001  # 导入file_001.pkg_001这个包

def test3():
	pass

  在__init__.py中可以添加一些初始化内容,因为在导入包时会首先执行下__init__.py这个文件。

Python模块导入时全局变量__all__的作用_python_chuan_day 20180326

python里的“all ”作用 - 脚本小娃子 20170824

导入类

二级标题

  

待补充

  

待补充

  



文字居中

数学公式粗体 \textbf{} 或者 m e m o r y {\bf memory} memory
数学公式粗斜体 \bm{}

摘录自“bookname_author”
此文系转载,原文链接:名称 20200505

高亮颜色说明:突出重点
个人觉得,:待核准个人观点是否有误

分割线

分割线


我是颜色为00ffff的字体
我是字号为2的字体
我是颜色为00ffff, 字号为2的字体
我是字体类型为微软雅黑, 颜色为00ffff, 字号为2的字体

分割线

分割线
##问题记录
问题描述
  开始
原因分析:
  开始
解决方案:
  开始

Markdown表格

方法命令备注
内容内容内容
内容内容内容

为长文本指定列宽实现换行

xxx
| xxx | xxx xxx |
very very very long long long text
| xxx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值