本文汇总一些python常见的内置函数以及python类的内置函数

1.breakpoint()

该函数可以在不适用IDE的情况下debug python代码,十分方便在服务器上调试代码(但是需要python 3.7+)

x = 1
print(x)
breakpoint()
x = 2
print(x)

上述代码在运行到breakpoint()时会进入pdb模式(python debug的缩写),可以支持查看/修改变量的值。

当运行到breakpoint()时程序会停止:

1
> /Users/sniper/PycharmProjects/MyE2E/test.py(27)<module>()
-> x = 2
(Pdb) 

进入pdb模式,在这里我们可以输入变量名查看变量的值,或者输入表达式:

1
> /Users/sniper/PycharmProjects/MyE2E/test.py(27)<module>()
-> x = 2
(Pdb) x
1
(Pdb) x=3
(Pdb) x
3
(Pdb) 

按c执行到下一个断点,按n执行下一步。

1
> /Users/sniper/PycharmProjects/MyE2E/test.py(27)<module>()
-> x = 2
(Pdb) x
1
(Pdb) x=3
(Pdb) x
3
(Pdb) c
2

2.dir()

查看属性、方法列表等。

class fun():
    def __init__(self):
        self.x = 1

    def test(self):
        pass


print(dir())
print(dir(fun))
print(dir(fun()))

当dir携带参数时,输出的是当前调用路径可以访问的变量、方法。而当参数为一个尚未实例化的类时,可以看到方法,而传入实例化后的类时,可以看到方法和属性。(只有最后一个有‘x’)

['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fun']

['__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__', 'test']

['__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__', 'test', 'x']

3.__init__

类的初始化方法,主要是初始化类中的一些参数。

class A():
    print('a')

    def __init__(self):
        print('init')



a = A()  
# output:
# a
# init

但是它的调用顺序晚于类中声明的变量。

4.__new__

python类分配空间的方法。当创建对象时,python会首先调用__new__来为对象分配空间。

class A():
    print('a')

    def __init__(self):
        print('init')

    @staticmethod
    def __new__(cls, *args, **kwargs):
        print('new')
        return super().__new__(cls)

    def fun(self):
        print('fun')


a = A()
# output:
# a
# new
# init

当解析器调用__new__时,__new__负责在内存中为该对象分配空间,同时返回对象的引用(self),随后将self传给__init__ 。 重写__new__的方法十分固定,就是 $ return\ super().\_\_new\_\_(cls) $。由于该方法负责申请内存空间,因此在该方法中可以很方便的实现单例模式。

class A():
    A = None

    def __init__(self):
        print('init')

    @staticmethod
    def __new__(cls, *args, **kwargs):
        print('new')
        if cls.A is None:
            cls.A = super().__new__(cls)
            return A
        else:
            return A

    def fun(self):
        print('fun')


a = A()
print(id(a))  # 4402021120
b = A()
print(id(b))  # 4402021120

虽然创建了很多”实例“,但是他们的地址都是同一个。

5.super()

一个用来调用父类的一个方法

class A():
    def __init__(self):
        print('A')


class B(A):
    def __init__(self):
        print('B')
        super(B, self).__init__()
        A.__init__(B)


B()
# output:
# B
# A
# A

可以看到,使用super()调用了父类的__init__函数,当然也可以显式的进行调用,这里结果是一样的,但是有一点点不一样,在稍后会提到。

6.__mro__

该方法的值是一个元组,它会按照方法解析顺序存放各个超类的名称。

在一些复杂的继承场景时,我们可能没办法立刻判断这些父类的初始化逻辑

class A():
def __init__(self):
print('A')


class B(A):
def __init__(self):
print('B')
super(B, self).__init__()


class C(A):
def __init__(self):
print('C')
super(C, self).__init__()


class D(B, C):
def __init__(self):
print('D')
super(D, self).__init__()


print(D.__mro__)
D()
# output:
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# D
# B
# C
# A

而通过__mro__我们就可以看出父类的初始化逻辑,与实际的调用顺序一致。

同时还可以发现,__mro__的输出并不重复(B和C的父类都是A,但是却只出现了一次),因此也就避免了重复初始化的问题。而super()也正是沿着__mro__进行初始化的,因此相比显式的直接调用__init__,使用super()调用__init__则没有重复调用的问题。

7.__str__

类似于java的toString(),可以显示的指定当前类的打印结果。

class A():
def fun(self):
pass

def __str__(self):
return 'is class A'


print(A) # <class '__main__.A'>
print(A()) # is class A

8.__call__

允许对象的实例直接调用的方法。如下,可以用过实例名()调用。当然也可以通过.调用其他方法。

class A():

def __call__(self, *args, **kwargs):
print(kwargs)

def fun(self):
print('fun')


a = A()
a(a=1, b=2) # {'a': 1, 'b': 2}
a.fun() # fun

9.@property

@property是python的一种装饰器,用来修饰方法的。

我们使用@property装饰器来创建只读属性,它会将方法转换为同名的只读属性,这样可以防止属性被篡改。

class A():

    def __init__(self):
        self._name = 'A'

    @property
    def fun(self):
        return 'fun in ' + str(self._name)

a = A()
print(A().fun)  # fun in A
print(a._name)  # A
a._name = 'B'
print(a._name)  # B

使用@property修饰后的方法,可以当做属性一样调用(也只能当做属性调用),同时由于可以隐藏属性名,因此也可以防止属性被篡改(当然了,python并没有真实的私有变量,依然可以通过实例.name进行调用与修改)。

10.@方法名.setter

@property解释器提供了隐藏属性的方法,那如何更改这些属性呢?既然尽量隐藏某些属性名,总不能通过实例名.name进行更改吧,可以通过方法名.setter的方式进行更改,同时由于定义的是方法,还可以对数据进行检查。

class A():

def __init__(self):
self._name = 'A'

@property
def name(self):
return self._name

@name.setter
def name(self, name):
if len(name) <= 1:
raise Exception('name must be at least 1')
self._name = name


a = A()
print(a.name) # A
a.name = 'BB'
print(a.name) # BB
a.name = 'B'
print(a.name) # Exception: name must be at least 1

需要注意的是,这两个方法名必须一致,重载关系。

11.@方法名

@方法名 可以让被注释的方法拥有额外的功能,或者说改变这个函数的执行结果。

def login_check(func):
def wrapper(self, username, password):
if username == password == 'root':
return func(self, username, password)
raise Exception('wrong password')

return wrapper


class A():

def __init__(self):
self._name = 'A'

@login_check
def login(self, username, password):
print('login success')


a = A()
a.login(username='root', password='root')

上面这段代码就执行了登录前的用户名密码检查,通过装饰器,可以快速直观的切换不同的登录检查方式等。

后续再有再回来补充。

分类: Python

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注