跳至主要內容

Day 8:16 个类型函数和 10 个类对象相关的内置函数大盘点

AI悦创原创Python全栈60天精通之路Python全栈60天精通之路大约 10 分钟...约 3031 字

你好,我是悦创。

今天,学习 Python 与类型创建、管理自定义类相关的内置函数。

在讲解下面 26 个内置函数前,介绍一个非常重要的知识点:函数作用域问题。

在学习 Python 函数时,我们经常会遇到变量作用域的问题,有全局变量,局部变量等,Python 查找变量的顺序遵守 LEGB 规则,即遇到某个变量时:

  • 优先从它所属的函数(local)内查找;
  • 若找不到,并且它位于一个内嵌函数中,就再到它的父函数(enclosing)中查找;
  • 如果还是找不到,再去全局作用域(global)查找;
  • 再找不到,最后去内置作用域(build-in)查找。
  • 若还是找不到,报错。

如下例子,变量 c 在局部作用域(local)被发现;变量 b 在 parent 函数和 son 函数间(enclosing)被发现;变量 a 在全局作用域(global)被发现;min 函数属于 Python 中内置函数,所以在搜寻完 LEG 三个区域后,最终在 build-in 域被找到。

a = 10
def parent():
    b = 20
    def son():
        c = 30 # c: local 
        print(b + c) # b: enclosing
        print(a + b + c ) # a: global
        print(min(a, b, c)) # min : built-in 

    son()


In [72]: parent()
50
60
10

如下变量 d,在 LEGB 四个域都被搜寻一遍后,还是未找到,就会抛出 d 没有被发现的异常。

a = 10
def parent():
    b = 20
    def son():
        c = 30 # c: local 
        print(b + c) # b: enclosing
        print(a + b + c ) # a: global
        print(min(a, b, c)) # min : built-in 
        print(d) # 在 LEGB 四个域都未找到后,报错!

    son()

parent()

# NameError: name 'd' is not defined

1. 类型函数

1.1 bool([x])

测试一个对象是 True,还是 False。

In [38]: bool([0, 0, 0])
Out[38]: True

In [39]: bool([])
Out[39]: False

In [40]: bool([1, 0, 1])
Out[40]: True

1.2 bytes([source[, encoding[, errors]]])

将一个字符串转换成字节类型:

In [44]: s = "apple"

In [45]: bytes(s, encoding='utf-8')
Out[45]: b'apple'

1.3 str(object='')

将字符类型、数值类型等转换为字符串类型:

In [1]: i = 100

In [2]: str(i)
Out[2]: '100'

1.4 chr(i, /)

查看十进制整数对应的 ASCII 字符:

In [54]: chr(65)
Out[54]: 'A'

1.5 ord(c, /)

查看某个 ASCII 字符对应的十进制数:

In [60]: ord('A')
Out[60]: 65

1.6 dict()

class dict(**kwarg)
class dict(mapping, **kwarg)
class dict(iterable, **kwarg)

创建数据字典:

In [92]: dict()
Out[92]: {}

In [93]: dict(a='a',b='b')
Out[93]: {'a': 'a', 'b': 'b'}

In [94]: dict(zip(['a','b'],[1,2]))
Out[94]: {'a': 1, 'b': 2}

In [95]: dict([('a',1),('b',2)])
Out[95]: {'a': 1, 'b': 2}

1.7 object()

返回一个根对象,它是所有类的基类。

In [137]: o = object()

In [138]: type(o)
Out[138]: object

使用魔法函数 __dir__,查看 object 对象上的所有方法:

In [2]: o.__dir__()
Out[2]:
['__repr__',
 '__hash__',
 '__str__',
 '__getattribute__',
 '__setattr__',
 '__delattr__',
 '__lt__',
 '__le__',
 '__eq__',
 '__ne__',
 '__gt__',
 '__ge__',
 '__init__',
 '__new__',
 '__reduce_ex__',
 '__reduce__',
 '__subclasshook__',
 '__init_subclass__',
 '__format__',
 '__sizeof__',
 '__dir__',
 '__class__',
 '__doc__']

1.8int(x)

int(x, base =10),x 可能为字符串或数值,将 x 转换为一个整数s

In [16]: int('12')
Out[16]: 12
In [120]: int('12', 16)
Out[120]: 18

若 x 不能转化为整数,则抛出 ValueError 异常:

In [3]: int('ws')
ValueError: invalid literal for int() with base 10: 'ws'

1.9 float(x=0, /)

将一个字符串或整数转换为浮点数:

In [103]: float('30')
Out[103]: 30.0

1.10 frozenset([iterable])

创建一个不可修改的冻结集合,一旦创建不允许增删元素。

In [30]: s = frozenset([1, 1, 3, 2, 3])

In [31]: s
Out[31]: frozenset({1, 2, 3})
image-20200219175754078
image-20200219175754078

但是,普通集合 set 创建后,仍然可以增删元素。

创建一个普通集合 s:

In [26]: s= {1, 2, 3}

创建 s 后,仍然能通过 add 方法,再插入元素:

In [28]: s.add(4)

In [29]: s
Out[29]: {1, 2, 3, 4}

普通集合也能删除元素,使用 pop 方法移除集合的第一个元素:

In [35]: s = {1, 2, 3}
In [36]: s.pop()
Out[36]: 1

In [37]: s
Out[37]: {2, 3}

1.11list([iterable])

返回可变序列类型:列表。如下,集合类型转列表:

In [38]: s = {1, 2, 3}

In [39]: list(s)
Out[39]: [1, 2, 3]

list 函数还常用在,可迭代类型(Iterable)转化为列表。

如下,使用 map 函数,转化列表内每一个整形元素为字符串型。

m 是可迭代类型,经过 list 转化后,看到列表 l。

In [43]: m = map(lambda i:str(i), [186,1243,3201])
Out[43]: l = list(m)

相似的一个例子:

In [85]: list(map(lambda x: x%2==1, [1, 3, 2, 4, 1]))
Out[85]: [True, True, False, False, True]

1.12 range(stop);range(start, stop[,step])

Python 提供两个内置的 range 函数,生成不可变序列:

In [153]: range(11) # 只有一个参数,默认初始值为 0,步长为 1
Out[153]: range(0, 11)

In [154]: range(0, 11, 1) #三个参数都提供,分别是开始、终止、步长值
Out[154]: range(0, 11)

1.13 set([iterable])

返回一个集合对象,并允许创建后再增加、删除元素。

集合的一大优点,容器里不允许有重复元素,因此可对列表内的元素去重。

In [159]: a = [1, 4, 2, 3, 1]

In [160]: set(a)
Out[160]: {1, 2, 3, 4}

1.14 slice(stop);slice(start, stop[, step])

返回一个由 range(start, stop, step) 所指定索引集的 slice 对象:

In [170]: a = [1, 4, 2, 3, 1]

In [171]: a[slice(0, 5, 2)] # 等价于 a[0: 5: 2]
Out[171]: [1, 2, 1]

1.15 tuple([iterable])

创建一个不可修改的元组对象:

In [59]: t = tuple(range(10))

In [60]: t
Out[60]: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

1.16 type(object);type(name, bases, dict)

这是两个查看对象的类型的函数。

自定义类 Student,创建实例 xiaoming:

In [61]: class Student:
    ...:     pass
In [63]: xiaoming = Student()

调用 type 查看 xiaoming 的类型:

In [64]: type(xiaoming)
Out[64]: __main__.Student

type 函数是非常实用的,阅读他人代码时,若函数参数类型没有显示给出,就会用到 type 函数。

In [187]: type((1, 2, 3))
Out[187]: tuple

1.17 zip(*iterables)

创建一个迭代器,聚合每个可迭代对象的元素。

参数前带 *,意味着是可变序列参数,可传入 1 个,2 个或多个参数。

传入 1 个参数:

In [68]: for i in zip([1, 2]):
    ...:     print(i)
    ...:
(1,)
(2,)

传入 2 个参数:

In [191]: a = range(5)
In [192]: b = list('abcde')
In [193]: b
Out[193]: ['a', 'b', 'c', 'd', 'e']
In [194]: [str(y) + str(x) for x, y in zip(a, b)]
Out[194]: ['a0', 'b1', 'c2', 'd3', 'e4']

2. 类对象及属性

2.1 classmethod

classmethod 修饰符对应的函数不需要实例化,不需要 self 参数。

第一个参数需要是表示自身类的 cls 参数,能调用类的属性、方法、实例等。

In [77]: class Student():
    ...:     def __init__(self,id=None,name=None):
    ...:         self.id = id
    ...:         self.name = name
    ...:
    ...:     def instance_method(self):
    ...:         print('这是实例方法')
    ...:         return self
    ...:
    ...:     @classmethod
    ...:     def __annotations__(cls):
    ...:         return "学生类"
    ...:
    ...:     @classmethod
    ...:     def print_type_name(cls):
    ...:         print('这是类上的方法,类名为 %s,注解为 %s'%(cls.__name__, cls.__annotations__()))
In [78]: Student().print_type_name()
    ...: Student().instance_method()
    ...:
这是类上的方法,类名为 Student,注解为学生类
这是实例方法
Out[78]: <__main__.Student at 0x154ef861308>

2.2 delattr(object, name)

删除对象的属性,在不需要某个或某些属性时,这个方法就会很有用。

In [79]: class Student():
    ...:     def __init__(self,id=None,name=None):
    ...:         self.id = id
    ...:         self.name = name

In [80]: xiaoming = Student(1,'xiaoming')

In [81]: delattr(xiaoming,'id')

In [82]: xiaoming.id
AttributeError: 'Student' object has no attribute 'id'

In [88]: hasattr(xiaoming,'id') # xiaoming 上没有 id 属性
Out[88]: False

2.3 dir([object])

不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时返回参数的属性、方法列表。

In [96]: dir(xiaoming)
Out[96]:
['__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']

2.4 getattr(object, name[, default])

获取对象的属性:

In [79]: class Student():
    ...:     def __init__(self, id=None, name=None):
    ...:         self.id = id
    ...:         self.name = name

In [106]: getattr(xiaoming,'name')
Out[106]: 'xiaoming'

2.5 hasattr(object, name)

In [79]: class Student():
    ...:     def __init__(self, id=None, name=None):
    ...:         self.id = id
    ...:         self.name = name

In [110]: hasattr(xiaoming, 'name')
Out[110]: True

In [81]: delattr(xiaoming, 'id')

In [111]: hasattr(xiaoming, 'id')
Out[111]: False

2.6 isinstance(object, classinfo)

判断 object 是否为类 classinfo 的实例,若是,返回 true。

In [79]: class Student():
    ...:     def __init__(self, id=None, name=None):
    ...:         self.id = id
    ...:         self.name = name

In [21]: xiaoming = Student('001','xiaoming')
In [22]: isinstance(xiaoming,Student)
Out[22]: True

序列类型的基类为 Iterable,所以返回 True:

In [85]: from collections.abc import Iterable

In [84]: isinstance([1, 2, 3],Iterable)
Out[84]: True

2.7 issubclass(class, classinfo)

如果 class 是 classinfo 类的子类,返回 True:

In [27]: class undergraduate(Student):
    ...:     def studyClass(self):
    ...:         pass
    ...:     def attendActivity(self):
    ...:         pass
    ...:

In [28]: issubclass(undergraduate, Student)
Out[28]: True

In [29]: issubclass(object, Student)
Out[29]: False

In [30]: issubclass(Student, object)
Out[30]: True

classinfo 取值也可能为元组,若 class 是元组内某个元素类型的子类,也会返回 True:

In [26]: issubclass(int, (int, float) )
Out[26]: True

2.8 property(fget=None, fset=None, fdel=None, doc=None)

返回 property 属性。不适用装饰器,定义类上的属性:

class Student:
    def __init__(self):
        self._name = None

    def get_name(self):
        return self._name

    def set_name(self, val):
        self._name = val

    def del_name(self):
        del self._name

    # 显示调用 property 函数    
    name = property(get_name, set_name, del_name, "name property")

显示的调用 property 函数定义类上的属性:

In [94]: xiaoming = Student()
    ...: xiaoming.name = 'xiaoming'

In [95]: xiaoming.name
Out[95]: 'xiaoming'

使用 Python 装饰器 @property,同样能实现对类上属性的定义 ,并且更简洁:

class Student:
    def __init__(self):
        self._name = None

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

    @name.setter
    def name(self, val):
        self._name = val

    @name.deleter
    def name(self):
        del self._name
In [98]: xiaoming = Student()

In [99]: xiaoming.name = 'xiaoming'

In [101]: xiaoming.name
Out[101]: 'xiaoming'

2.9 super([type[, object-or-type]])

返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。

如下,子类的 add 方法,一部分直接调用父类 add,再有一部分个性的行为:打印结果。

In [1]: class Parent():
    ...:     def __init__(self, x):
    ...:         self.v = x
    ...:
    ...:     def add(self,x):
    ...:         return self.v + x

In [2]: class Son(Parent):
    ...:     def add(self, y):
    ...:         r = super().add(y) #直接调用父类的add方法
    ...:         print(r) #子类的add与父类相比,能实现对结果的打印功能
    ...:

In [3]: Son(1).add(2)
3

2.10 callable(object)

判断对象是否可被调用,能被调用的对象就是一个 callable 对象,比如函数 str、int 等都是可被调用的。

In [1]: callable(str)
Out[1]: True

In [2]: callable(int)
Out[2]: True

如下,xiaoming 实例不可被调用:

In [79]: class Student():
    ...:     def __init__(self, id=None, name=None):
    ...:         self.id = id
    ...:         self.name = name

In [21]: xiaoming = Student('001', 'xiaoming')

In [4]: callable(xiaoming)
Out[4]: False

如果 xiaoming 能被调用:

xiaoming()

必须要重写 Student 类上 __call__ 方法:

In [1]: class Student():
    ...:     def __init__(self, id, name):
    ...:         self.id = id
    ...:         self.name = name
    ...:     def __call__(self):
    ...:         print('I can be called')
    ...:         print(f'my name is {self.name}')

In [2]: t = Student('001', 'xiaoming')

In [3]: t()
I can be called
my name is xiaoming

3. 小结

今天学习 26 个内置函数:

  • 16 个 Python 内置的与类型相关的函数
  • 10 个与自定义类属性、方法管理相关

欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!

公众号:AI悦创【二维码】

AI悦创·编程一对一

AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh

C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh

方法一:QQopen in new window

方法二:微信:Jiabcdefh

上次编辑于:
贡献者: AndersonHJB
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度