大家好,我是练习时长两年半的大数据练习生,喜欢数学,AI,大数据。
写博客是为了总结,分享,自娱自乐
。希望写出的东西会对自己,对别人都有价值!
废话不多说,现在是个终身学习的时代,开始学习了!奥力给!干了兄弟们!
是时候展现真正的技术了:
本文是一篇学习笔记,外加百度上搜刮来的知识,外加自己总结的知识:
原文链接:https://faker.readthedocs.io/en/master/fakerclass.html#proxy-class-implementation-details
第一种 2.0.4版本及以下常用写法
from faker import Factory
fake = Factory.create()
第二种 新版本创建Faker代理类而不是Factory.create()
from faker import Faker
fake = Faker()
第一种是老版本的,第二种是新版本的,两种都可以使用,但是在seed()上有一点区别
在新版本Faker类的基础上,你不能调用类的实例.seed()
方法了,会报类型错误,取而代之的是Faker.seed()
在新版本Faker类基础上用旧版本写法会抛出异常:
from faker import Faker
fake = Faker()
fake.seed(0) # 抛出异常TypeError
现在你得用新版本的写法:
from faker import Faker
fake = Faker()
Faker.seed(0)
如果你一定要用老版本的写法,那你创建Faker对象的时候要用老版本Factory.create()
的创建方法。
新的Faker实例只是引用了Generator对象的代理对象,它用于实例化时指定使用的语种,这些Generator对象们只是旧Faker对象的不同的实例而已。
如果只有一个内部的Generator对象,那新的Faker实例就只支持一种语言,如果有多个内部Generator对象,那么Faker实例就会支持多种语言。
在单语种模式下,新的Faker实例可以简单的被迫表现为像是用旧Faker创建出来的实例一样,因为类似的接口可以在新的Faker实例上公开,然后1:1地调用代理方法、properties和attributes到唯一的生成器对象。事实上,这就是实现它的方式,也是保持向后兼容性的方式(除了Faker.seed()
)。
然而,在多语种模式下,这种1:1映射不再存在了,调用的代理方式取决于属性是一个provider
的方法或者是存在于生成器对象中的某个属性。有可能提供健全的默认实现,像我们为seed_instance
所做的那样巧妙地映射,但是其他的像add_provider
和随机的getter
和setter
更依赖于特定的用例,或者有潜在的危险。
在这些情况下,对使用者来说更好的情况是用它们的实现或者直接调用这些来自于内部Generator对象自己的方法来创建它们自己的子类
(这一段翻译过来我也没看懂是啥意思,等我后边懂了再回来注解或者修改把)
这个代理类指新版本Faker类。
代理类有一个属性名称解析行为,运行顺序如下:
seed
,那就抛出TypeError
异常,这样可以防止实例调用seed
方法(与上文呼应,新版Faker类的实例不能调用seed()
方法而是Faker.seed()
)seed
,那就检查属性名称是否与代理类实例中的属性匹配。如果匹配就返回匹配的属性。NotImplementedError
.AttributeError
,因为如果匹配的话,第二步就应该处理完了。provider
的方法,并且进行Generator/Factory
模式的选择,并且代理调用被选中的Generator
对象Factory/generator 的选择将会在后边讨论
一个新的Faker实例会在单语种或多语种环境下工作,取决于你传递的locale
值,这个值可以是下面的几种:(下划线是_
连字符是-
)
前两个老Faker支持,所以新Faker也支持,所以调用前两个总会生成一个单语种模式的新Faker实例,在这个模式下,实际上不需要检索对内部Generator对象的引用
,因为前面讨论过的1:1行为。
潜在的缺陷存在于多语种模式下和需要单独访问内部生成器对象时。由于语言环境字符串可以用(en_US)
或者(en-US)
编写,这可能导致混乱或错误,所以语言环境字符串必须被规范化处理,以提供一致的没有重复的结果。
在实例化过程中,新Faker会将语言环境字符串规范为下划线的形式,它也会按照原样存储它们,换句话说,en_US和en-US都被指定时,将会被视为相同的。最后被处理的将会被看作副本,重复的,然后被清除。通过索引访问内部Generator对象时也会执行对应的正则。
例如,下面的代码将会创建一个新Faker实例,即使你制定了4个地区,这个新Faker实例也是单语种模式下的。
"""
即使你指定了4个语种,它也是单语种模式下的
"""
from faker import Faker
fake = Faker(['en-US', 'en_US', 'en_US', 'en-US'])
# 将会打印 ['en_US']
print(fake.locales)
# 获得 en-US generator 的引用
us1 = fake['en_US']
# 获得 en-US generator 的引用
us2 = fake['en-US']
# 将会打印 True
print(us1 == us2)
为了启动多语种模式,参数local
的值必须是由不止一个有效的语言环境字符串组成的列表,元组,集合或OrderedDict
例如:
from collections import OrderedDict
from faker import Faker
locale_list = ['en-US', 'ja-JP', 'en_US']
fake1 = Faker(locale_list)
# 将会打印 ['en_US', 'ja_JP']
print(fake1.locales)
locale_odict = OrderedDict([
('en-US', 1),
('ja-JP', 2),
('en_US', 2),
])
fake2 = Faker(locale_odict)
# 将会打印 ['en_US', 'ja_JP']
print(fake1.locales)
在多语种模式下,从新Faker实例中调用预期的provider方法将会运行Factory/Selection逻辑。
Factory/Selection逻辑如下:
provider
的方法中,如果存在那就使用这个映射,provider
的方法,如果没有,那将会像使用旧Faker一样抛出AttributeError
除了能够提供给每个语种对应的生成概率,并且最小化性能损失之外,factory selection逻辑保证了只要至少有一个generator对象支持provider的方法,那调用provider方法就不会失败。
如果你能看懂下面这些代码,那说明你理解了上面的内容,恭喜。
from collections import OrderedDict
from faker import Faker
locales = OrderedDict([
('en-US', 1),
('en-PH', 2),
('ja_JP', 3),
])
fake = Faker(locales)
# 获取实例化期间指定的地区列表
print(fake.locales)
# 获取这个Faker对象的内部生成器列表
print(fake.factories)
# 获取'en_US' locale的内部生成器
print(fake['en_US'])
# 获取“en_PH”语言环境的内部生成器
print(fake['en_PH'])
# 获取“ja_JP”语言环境的内部生成器
print(fake['ja_JP'])
# 瞎写地区将会抛出 KeyError 并提示 'en_GB' was not included
print(fake['en_GB'])
# 设置共享的`random.Random` 对象的seed
# 跨越所有将被创建的内部生成器
Faker.seed(0)
# 设置唯一的`random.Random` 对象的seed
# each internal generator of this `Faker` instance
fake.seed_instance(0)
# 为这个Faker实例的 en_US内部 generator创建并seed一个独一无二的 `random.Random` 对象
fake.seed_locale('en_US', 0)
# 在提供权重的基础上创建一个随机的name
# 生成特定语言的概率 = 每种语言的权重/所有语言加起来总权重
# en_US - 16.67% of the time (1 / (1 + 2 + 3))
# en_PH - 33.33% of the time (2 / (1 + 2 + 3))
# ja_JP - 50.00% of the time (3 / (1 + 2 + 3))
fake.name()
# 生成一个en_US语种下的name
fake['en-US'].name()
# 生成一个建立在提供的权重的基础上的 zipcode
# 注意: en_PH 并不支持 zipcode provider 方法
# en_US - 25% of the time (1 / (1 + 3))
# ja_JP - 75% of the time (3 / (1 + 3))
fake.zipcode()
# 生成一个在 ja_JP 语种下的zipcode
fake['ja_JP'].zipcode()
# 将会抛出 AttributeError
fake['en_PH'].zipcode()
# 生成一个 Luzon province 的名字
# 注意: 创建时提供的三种语种之中只有 en_PH 支持这个 provider 方法
fake.luzon_province()
# 生成一个 Luzon province name
fake['en_PH'].luzon_province()
# 抛出一个 AttributeError
fake['ja_JP'].luzon_province()
小伙伴们!相信看到这里的你一定有所收获!
如果我哪里写错欢迎评论区来喷
如果觉得对你有帮助请给个赞哦亲
!爛爛爛爛爛爛
爛爛爛最后引用名言一句
:我们无论遇到什么困难,都不要怕,微笑着面对它!消除恐惧的最好办法就是面对恐惧!加油!奥力给!