7.9 类的实践

    其实类背后所承载的理念是 OOP(面向对象)的编程理念。在大型项目中为了易于管理和维护代码质量,会采取面向对象的方式,这也是软件工程的智慧所在。接下来,我们将使用类的概念来编写一个日常的工具库导入到 Python 的库中,这样一来我们也可以使用 import 方法导入自己的库了。

    在使用 Python 处理数据或者是开发网站时,有时候会使用一些无意义的假数据,比如用户详情页信息。

    我们来制作这样一个填充用户假数据的小工具,这个小工具的设计思路如下:

    父类:FakeUser
    功能:
    • 随机姓名
    a. 单字名
    b. 双字名
    c. 无所谓是什么反正有个名字就好了
    • 随机性别
    子类:SnsUser
    功能:
    • 随机数量的跟随者
    a. few
    b. a lot

    在开始之前先来处理一下词库,我们使用的随机姓名的词库来自于某输入法的姓名词库解析后的结果,现在分成两个文件,一个是常见姓氏,一个是常见的名。使用 open 函数打开这两个文件,将其中的文字添加进列表中。我们获取全部的常见姓氏,后面的姓名只获取5000个即可,否则太占内存。

    ln_path = '/Users/Hou/Desktop/last_name.txt'
    fn_path = '/Users/Hou/Desktop/first_name.txt'
    fn = []
    ln1 = [] #单字名
    ln2 = [] #双字名
    with open(fn_path,'r') as f:
    for line in f.readlines():
    fn.append(line.split('\n')[0]) #如果这里看不明白不妨试试対其中的一行使用 split 方法看看会返回回来什么结果
    print(fn)
    with open(ln_path,'r') as f:
    for line in f.readlines():
    if len(line.split('\n')[0]) == 1:
    ln1.append(line.split('\n')[0])
    else:
    ln2.append(line.split('\n')[0])
    print(ln1)
    print('='*70) #分割线
    print(ln2)

    打印完成后,我们做两件事情:

    • 将 fn = [] ln1 = [] ln2 = [] 修改改成元组,元组比列表要更省内存。
    • 将打印出来的结果复制粘贴到元组中,显然在制作完成后我们不能每做一次就重新读一遍,要把这些变成常量。

    完成后看起来应该像这样(当然比这个要长很多很多):

    fn = ('李', '王', '张', '刘')
    ln1 = ('娉', '览', '莱', '屹')
    ln2 = ('治明', '正顺', '书铎')

    现在开始我们可以来定义父类 FakeUser 了:

    import random
    class FakeUser:
    def fake_name(self,one_word=False,two_words=False):
    if one_word:
    full_name = random.choice(fn) + random.choice(ln1)
    elif two_words:
    full_name = random.choice(fn) + random.choice(ln2)
    else:
    full_name = random.choice(fn) + random.choice(ln1 + ln2)
    print(full_name)
    def fake_gender(self):
    gender = random.choice(['男','女','未知'])
    print(gender)

    接下来是定义子类:

    class SnsUser(FakeUser):
    def get_followers(self,few=True,a_lot=False):
    if few:
    followers = random.randrange(1,50)
    elif a_lot:
    followers = random.randrange(200,10000)
    print(followers)
    user_a = FakeUser()
    user_b = SnsUser()
    user_a.fake_name()
    user_b.get_followers(few=True)

    似乎这并没有解决什么问题?

    到了这里,我们创建的类已经可以正常使用了。我们的目的是批量制造假的填充数据,但是这样使用比起手工添加,效果并好不到哪去,因此在原有的代码上,我们要做一些小的调整,把所有的 print 替换成 yield 并在其上方加上一层循环,然后神奇的事情就这样发生了,我们就可以像 range 函数一样使用方法了:

    class FakeUser():
    def fake_name(self,amount=1,one_word=False,two_words=False):
    n = 0
    while n <= amount:
    if one_word:
    full_name = random.choice(fn) + random.choice(ln1)
    elif two_words:
    full_name = random.choice(fn) + random.choice(ln2)
    else:
    full_name = random.choice(fn) + random.choice(ln1 + ln2)
    yield full_name
    n+=1
    def fake_gender(self,amount=1):
    n = 0
    while n <= amount:
    gender = random.choice(['男','女','未知'])
    yield gender
    n +=1
    class SnsUser(FakeUser):
    def get_followers(self,amount=1,few=True,a_lot=False):
    n = 0
    while n <= amount :
    if few:
    followers = random.randrange(1,50)
    elif a_lot:
    followers = random.randrange(200,10000)
    yield followers
    n+=1
    user_a = FakeUser()
    user_b = SnsUser()
    for name in user_a.fake_names(30):
    print(name)
    for gender in user_a.fake_gender(30):
    print(gender)

    为什么?

    这其实用到了一个新的概念,叫做生成器(generator)。简单的来说,在函数中我们只要在任意一种循环(loop)中使用 yield 返回结果,就可以得到类似于 range 函数的效果。

    安装自己的库

    我们一般使用 pip 来进行第三方库的安装,那么自己的库要怎么安装呢?当然可以把自己的库提交到 pip 上,但是还要添加一定量的代码和必要文件才行。在这里我们使用一个更简单的方法:

    • 找到你的 Python 安装目录,找到下面的 site-packages 文件夹;
    • 记住你的文件名,因为它将作为引用时的名称,然后将你写的 py 文件放进去。

    这个文件夹应该有你所装的所有第三方库。

    如果你并不清楚你的安装路径,你可以尝试使用如下方式搞清楚它究竟在哪里:

    import sys
    print(sys.path)

    打印出来的会是一个列表,列表中的第四个将是你的库安装路径所在,因此你也可以直接这么做:

    import sys
    print(sys.path[3])

    现在就来试试使用自己写的库吧!

    练习题

    • 给子类设计增加一个新的方法——get_nick_name()