Python-__repr__、__hash__和__eq__方法,split()、join()、yield()和append()函数

1.__repr__方法

程序1

class Python:
    pass


a = Python()
print(a)
print(a.__repr__())

结果

<__main__.Python object at 0x0000023B82185FD0>
<__main__.Python object at 0x0000023B82185FD0>

默认情况下,我们得到的信息只会是“类名+object at+内存地址”

程序2

class Python:

    def __init__(self):
        self.name = "我喜欢你"
        self.add = "https://www.baidu.com"

    def __repr__(self):
        return "Python[name=" + self.name + ",add =" + self.add + "]"


a = Python()

print(a)   

结果

Python[name=我喜欢你,add =https://www.baidu.com]
  • 通过重写类的 __repr__() 方法可以自定义输出实例化对象时的信息,当输出某个实例化对象时,其调用的就是该对象的 __repr__() 方法,输出的是该方法的返回值。

  • 程序1中执行 print(a) 等同于执行 print(a.__repr__()),程序的输出结果是一样的(输出的内存地址可能不同)。

  • 和 __init__(self) 的性质一样,python 中的每个类都包含 __repr__() 方法,因为 object 类包含__reper__() 方法,而 Python 中所有的类都直接或间接继承自 object 类。

  • __repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,而如果对该方法进行重写,可以为其制作自定义的自我描述信息,如程序2

2.__hash__函数和__eq__函数

  • 可哈希的集合(hashed collections),需要集合的元素实现了__eq__和__hash__,而这两个方法可以作一个形象的比喻:哈希集合就是很多个桶,但每个桶里面只能放一个球。

  • __hash__函数的作用就是找到桶的位置,到底是几号桶。

  • __eq__函数的作用就是当桶里面已经有一个球了,但又来了一个球,它声称它也应该装进这个桶里面(__hash__函数给它说了桶的位置),双方僵持不下,那就得用__eq__函数来判断这两个球是不是相等的(equal),如果是判断是相等的,那么后来那个球就不应该放进桶里,哈希集合维持现状。

程序

class Python:
    def __init__(self, item):
        self.item = item

    def __eq__(self, other):
        print('使用了equal函数的对象的id',id(self))
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

    def __hash__(self):
        print('f'+str(self.item)+'使用了hash函数')
        return hash(self.item)


f1 = Python(1)
f2 = Python(2)
f3 = Python(3)
f_set = set([f1, f2, f3])
print(f_set)
print()
f = Python(3)
f_set.add(f)
print('f3的id:', id(f3))
print('f的id:', id(f))

结果

f1使用了hash函数
f2使用了hash函数
f3使用了hash函数
{<__main__.Python object at 0x000001E6F4271CA0>, <__main__.Python object at 0x000001E6F4271C40>, <__main__.Python object at 0x000001E6F4271B50>}

f3使用了hash函数
使用了equal函数的对象的id 2091450309456
f3的id: 2091450309456
f的id: 2091450309264

3.split函数

  • split()函数

语法:str.split(str="",num=string.count(str))[n]

  • 参数说明:

str:表示为分隔符,默认为空格,但是不能为空(’’)。若字符串中没有分隔符,则把整个字符串作为列表的一个元素

num:表示分割次数。如果存在参数num,则仅分隔成 num+1 个子字符串,并且每一个子字符串可以赋给新的变量

[n]:表示选取第n个分片

注意:当使用空格作为分隔符时,对于中间为空的项会自动忽略

程序

string = "abcade \nf.ghi.gk \nlmn"

print(string.split())  # 以空格为分隔符,包含 \n
print(string.split(' ', 1))  # 以空格为分隔符,分隔成两个

print(string.split("a", 1))  # 以 a 为分割符,指定第二个参数为 1,返回两个参数列表

结果

['abcade', 'f.ghi.gk', 'lmn']
['abcade', '\nf.ghi.gk \nlmn']
['', 'bcade \nf.ghi.gk \nlmn']

4.join函数

  • join()是一个字符串方法,它返回与iterable元素连接在一起的字符串。

  • join()方法提供了一种灵活的方式来连接字符串。它将可迭代的每个元素(如列表,字符串和元组)连接到字符串,并返回连接后的字符串。

join()的语法为:

string.join(iterable)
  • join()参数

join()方法采用一个可迭代的对象-能够一次返回其成员的对象

可迭代的一些示例是:

原生数据类型 - 列表,元组,字符串,字典和集合

  • join()返回值

join()方法返回一个与iterable元素串联的字符串。

如果Iterable包含任何非字符串值,则将引发TypeError异常。

join()函数如何用于列表和元组

程序

numList = ['1', '2', '3', '4']
seperator = ', '
print(seperator.join(numList))

numTuple = ('1', '2', '3', '4')
print(seperator.join(numTuple))

s1 = 'abc'
s2 = '123'

""" s2的每个字符都连接到s1的前面"""
print('s1.join(s2):', s1.join(s2))

""" s1的每个字符都连接到s2的前面"""
print('s2.join(s1):', s2.join(s1))

结果

1, 2, 3, 4
1, 2, 3, 4
s1.join(s2): 1abc2abc3
s2.join(s1): a123b123c

join()函数如何用于集合

程序

test = {'2', '1', '3'}
s = ', '
print(s.join(test))

test = {'Python', 'Java', 'Ruby'}
s = '->->'
print(s.join(test))

结果

2, 1, 3
Ruby->->Java->->Python

注意: 集合是项目的无序集合,您可能会获得不同的输出。

join()函数如何用于字典

程序

test = {'mat': 1, 'that': 2}
s = '->'
print(s.join(test))

test = {1:'mat', 2:'that'}
s = ', '

# 这抛出了错误
print(s.join(test))

结果

mat->that
Traceback (most recent call last):
  File "...", line 36, in <module>
    print(s.join(test))
TypeError: sequence item 0: expected str instance, int found

join()方法尝试将字典的键(而非值)连接到字符串。如果字符串的键不是字符串,则会引发TypeError异常。

5.yield函数

  • return:在函数中返回某个值,然后函数结束运行。一般没有返回值类型,就不用写return

  • yield:带yield的函数是一个迭代器,在函数内部碰到yield 的时候,函数会返回某个值,并停留在这个位置,当下次执行函数后,会在上次停留的位置继续运行。

  • yield首先是个return,在程序中返回某个值,返回之后程序就不再往下运行了。看做return之后再把它看做一个是生成器(generator)的一部分(带yield的函数才是真正的迭代器)

程序1

def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:", res)


g = foo()
print(next(g))
print("*"*20)
print(next(g))
  • 对代码进行单步调试

  • 程序开始执行以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)

  • 直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,然后进入while循环

  • 程序遇到yield关键字,然后把yield想想成return,return了一个4之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果

  • 程序执行print("*"*20),输出20个*

  • 又开始执行下面的print(next(g)),但这个是从刚才那个next程序停止的地方开始执行的,也就是要执行res的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候res赋值是None,所以接着下面的输出就是res:None

  • 程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

原文链接:https://blog.csdn.net/mieleizhi0522/article/details/82142856

结果1

starting...
4
********************
res: None
4

程序2

def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:", res)


g = foo()
print(next(g))
print("*"*20)
print(g.send(7))
  • send函数:send是发送一个参数给res的,程序1中return的时候,并没有把4赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。

  • 前两个print()的输出和程序1完全一致,重点讲解最后一个print()

  • 程序执行g.send(7),程序会从yield关键字那一行继续向下运行,send会把7这个值赋值给res变量

  • 由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环

  • 程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法

结果2

starting...
4
********************
res: 7
4

6.append函数

  • append() 方法向列表末尾追加元素

程序

fruits = ['apple',  'banana', 'cherry']

fruits.append("orange")
print(fruits)

结果

['apple', 'banana', 'cherry', 'orange']

程序

  • 向列表添加一个列表

a = ["apple", "banana", "cherry"]
b = ["Porsche", "BMW", "Volvo"]
a.append(b)

print(a)

结果

['apple', 'banana', 'cherry', ['Porsche', 'BMW', 'Volvo']]

猜你喜欢

转载自blog.csdn.net/aaaccc444/article/details/129114395