# 第19章 动态属性和特性"""
属性(attribute):数据的属性和处理数据的方法统称属性,方法只是可调用的属性.
特性(property)除此之外,我们海可以创建特性,在不改变类接口的前提下使用存取方法(即读值方法和设值方法)修改数据属性,这与统一访问原则相符
统一访问原则:不管服务是由存储还是计算实现的,一个模块提供的服务都应该通过统一的方式使用
python还提供了丰富的API,用于控制属性的权限,以及实现动态属性使用点号访问属性时(obj.attr):python解释器会调用特殊的方法(如__getattr__,__setattr__)计算属性用户自己定义的类可以通过__getsttr__方法实现"虚拟属性",当访问不存在的属性时即时计算属性的值
动态创建属性是一种元变成,在python中,相关基础技术十分简单,任何人都可以使用,甚至在
日常数据转换任务中也能用到.
"""# 19.1 使用动态属性转换数据
# 示例19-2 osconfeed.py:下载osconfeed.json# 19.1.1使用动态属性访问json数据
"""
读取这种嵌套的json数据时使用的feed['Schedule']['events'][40]['speakers'])语法很冗长
js中可以使用feed.Schedule.events[40].speakers表示python通过实现一个类似字典的类,能达到相同的效果
"""# 示例19-5 explore0.py:把一个json对象装换成一个嵌套着FrozenJSON对象,列表.和简单类型的FrozenJSON对象
# 19.1.2处理无效的属性名
"""
类FrozenJSON的缺陷,如果属性名是python中的关键字,就无法读取属性值
如 grad = FrozenJSON({'name':'Jim','class':1982})
grad.class就不能正确读取属性值
"""
# 19-6 explore0.py:在名称为python关键字的属性后面加上_# 19.1.3使用__new__方法以灵活的方式创建对象
"""
通常将__init__称为构造方法
实际上真正用于构建实例的方法是__new__,这是一个类方法使用特殊方式处理,因此不用加@classmethod它必须返回一个实例,返回的实例作为__init__的self参数传递给__init__实际使用中几乎不用自己编写__new__方法,从object继承来的实现已经足够
python构建对象的伪代码:
def object_maker(the_class,some_arg):new_object = the_class.__new__(some_arg)if isinstance(new_object,the_class):the_class.__init__(new_object,some_arg)return new_object
# 下述两个语句的作用基本等效
x = Foo('bar')
x = object_maker(Foo,'bar')
"""# 实例19-7 explore2.py:使用__new__方法取代build方法# 19.1.4 使用shelve模块调整OSCON数据源的结构
"""
shelve模块:提供了对象序列化pickle存储方式shelve.open高阶函数返回一个shelve.Shelf实例这是简单的键值对象数据库,背后由dbm支持shelve.Shelf是abc.MutableMapping的子类shelve.Shelf还提供了几个管理I/O的方法,如sync和close,它也是一个上下文管理器只要把新值赋予键,就会保存键值对键必须是字符串值必须是pickle模块能处理的对象
"""
# 示例19-9 schedule1.py:访问保存再shelve.Shelf对象里的OSCON数据
"""
对象的__dict__属性,存储着对象的属性,前提是类中没有申明__slot__属性
因此更新__dict__,把值设为一个映射,能快速地在那个实例中创建一堆属性
"""# 19.1.5使用特性获取链接的记录
"""
特性经常用于把公开的属性变成使用读值方法和设值方法管理的属性
且在不影响客户端代码的前提下实施业务规则"""# 19.2 使用特性验证属性# 19.2.1 LineItem类第一版:表示订单中商品的类
"""
假设有个销售散装有机食品的电商应用,客户可以按重量订购坚果,干果或杂粮,
在这个系统中,每个订单都有一些列的商品,而每个商品都可以通过下例的类表示
"""
# 示例19-15 bulkfood_v1.py:最简单的LineItem类# 19.2.2 LineItem类第二版:能验证值的特性
"""
使用特性以后,我们可以使用读值方法和设值方法,但是类的接口保持不变,即
设置LineItem对象的weight属性仍然写成raisins.weight = 12
"""
# 示例19-17 bulkfood_v2.py:定义了weight特性的LineItem类"""
第二版把weight属性变成了特性,用户无法再给weight赋值负数或者0,
为防止工作人员出错,可以把price属性作相同的操作,但是就存在重复
去除重复的方法是抽象抽象特性的方式:使用特性工厂函数使用描述符类
"""# 19.3 特性的全面解析
"""
内置的property经常用作装饰器,但它其实是一个类在python中,函数和类通常可以互换,因为二者都是可调用对象而且没有实例化对象的new运算符,所有调用构造函数和调用工厂函数没有什么区别此外只要能够返回新的可调用对象,代替被装饰的函数,二者都可以用作装饰器property完整的构造方法:property(fget = None,fset=None,fdel=None,doc=None)所有的参数都是可选的如果没有把函数传给某个参数,那么得到的特性对像就不允许执行相应的操作
"""# 19.3.1特性会覆盖实例属性
"""
特性都是类属性,但是特性管理的其实是实例属性的存取
如果实例和所属的类有同名属性,那么实例属性会覆盖类的数据属性
""""""
# 示例 19-19 实例属性覆盖类的数据属性
class Class: # 定一个类,它有两个属性 数据属性data和特性propdata = 'the class data attr'@propertydef prop(self):return 'the prop value'
obj = Class()
# vars(obj)返回obj的__dict__属性,这里表明没有实例属性
print(vars(obj))  # {}
print(obj.data)   # the class data attr
obj.data = 'bar'  # 为obj.data赋值,创建一个实例属性
# 此时实例属性覆盖了类属性data
print(vars(obj))  # {'data': 'bar'}
print(obj.data)  # bar
# 类属性data的值完好无损
print(Class.data)  # the class data attr# 实例属性不会覆盖类的特性 19-20# 直接从类中读取prop,获取的是特性对象本身,不会运行特性的读值方法
print(Class.prop)  # <property object at 0x0000017F837DC540>
# 读取obj.prop会执行特性的读值方法
print(obj.prop)  # the prop value
# 尝试设置prop实例属性,结果失败
# obj.prop = 'foo'  # AttributeError: can't set attribute
# 但是可以直接把'prop'存入obj.__dict__
obj.__dict__['prop'] = 'foo'
print(vars(obj))  # {'data': 'bar', 'prop': 'foo'} obj现在有两个实例属性
print(obj.prop)  # the prop value  然而读取obj.prop任然会执行特性的读值方法
Class.prop = 'baz'  # 覆盖Class.prop特性,销毁特性对象
print(obj.prop)  # foo  现在obj.prop获取的是实例属性print("==============================")
# 19-21 为class类新添一个特性,覆盖实例属性
print(obj.data)  # bar  获取的是实例属性
print(Class.data)  # the class data attr  获取的是类属性
Class.data = property(lambda self:'the "data" prop value')  # 使用新特性覆盖Class.data
print(obj.data)    # the "data" prop value  被特性覆盖了
del Class.data  # 删除特性
print(obj.data)  # bar  实例属性恢复
"""# 总结:
# obj.attr这样的表达式不会从obj开始寻找attr,而是从obj.__class__开始,
# 仅当类中没有名为attr的特性时,python才会在obj的实例中找
# 这条规则不仅适用于特性,还适用于一整类描述符--覆盖型描述符(overrriding descriptor)# 19.3.2特性的文档
# 控制台中的help()函数或IDE等工具需要显示特性的文档时,会从特性的__doc__中提取
# weight = property(........doc='weight in kilograms')
# 使用装饰器创建property对象时,读值方法的文档字符串作为一个整体,变成特性的文档# 19.4定义一个特性工厂函数
# 就不用手动实现两队一模一样的读值方法和设值方法了
# 示例 19-24 bulkfood_v2prop.py:quantity特性工厂函数# 19.5处理属性的删除操作
# 示例19-26 blackknight.py:定义特性删除方法# 19.6 处理属性的重要属性和函数# 19.6.1影响属性处理方式的特殊属性
"""
__class__:对象所属类的引用(即obj.__class__与type(obj)的作用相同)python的某些特殊方法只在对象的类中寻找,而不在实例中寻找,如__getattr__
__dict__:一个映射,存储对象或类的可写属性,有__dict__属性的对象,任何时候都能随意设置新的属性如果类有__slots__属性,它的实例可能没有__dict__属性
__slots__:类可以定义这个属性,限制实例可以有哪些属性,其值是一个由字符串组成的元组,指明允许有的属性如果__slots__中没有__dict__属性,那么该类的实例没有__dict__属性
"""# 19.6.2处理属性的内置函数
# 以下5个内置函数对对象的属性做读/写/内省操作
"""
dir([object]):列出对象的大多数属性能审查有或者没有__dict__的对象不会列出__dict__属性本身,但会列出其中的键不会列出几个特殊的属性:__mro__,__bases__,__name__如果没有指定可选参数object,返回当前作用域中的名称
getattr(object,name[,default]):从obj获取name字符串对应的属性获取的属性可能来自对象的类或者超类如果没有指定的属性,抛出AttributeError,或者返回default参数的值(如果设置了的话)
hasattr(obj,name):如果obj对象存在指定的属性,或者能以某种方式(例如继承)通过obj对象获取指定的属性,则返回True
setattr(obj,name,value):把obj对象指定属性的值设置为value,前提是obj对象能接受这个值这个函数可能会创建一个新属性,或者覆盖现有的属性
vars([object]):返回obj对象的__dict__属性,如实例没有__dict__属性(设置了__slots__),那么不能处理,相反dir()可以处理省略object效果和dir相同
"""# 19.6.3处理属性的特殊方法
# 在用户自己定义的类中,下列特殊方法用于获取\设置\删除\列出属性
"""
使用.或者内置的getattr/setattr/hasattr函数存取属性都会触发下述列表中相应的特殊方法
但是直接通过__dict__读写属性不会触发,如果需要,通常使用这种方式跳过特殊方法obj.attr和getattr(obj,'attr',42)都会触发 Class.__getattribute__(obj,'attr')特殊方法__delattr__(self,name):使用del 删除属性就会调用这个方法 del obj.attr 调用Class.__delattr__(obj,'attr')__dir__(self)把对象传给dir()时调用,列出属性dir(obj)触发 Class.__dir__(obj)方法__getattr__(self,name):仅当获取指定的属性失败,搜索过obj,Class,和超类之后调用__getattribute__(self,name):尝试获取指定的属性时,总会调用这个方法,不过寻找的属性是特殊属性或特殊方法时除外.号和getattr(),hasattr()会触发这个方法调用这个方法触发AttributeError时,调用__getattr__()为了在获取obj实例属性时不导致无限递归,__getattribute__方法的实现要使用super().__getattribute__(obj,name)
__srtsttr__(self,name,value):尝试设置指定的属性时总会调用这个方法obj.attr = 42和setattr(obj,'attr',42)都会触发 Class.__setattr__(obj,'attr',value)
"""# 本章总结:
"""
本章的话题是动态属性编程"""
# 示例19-2 osconfeed.py:下载osconfeed.json
# 示例19-2 osconfeed.py:下载osconfeed.json
from urllib.request import urlopen
import warnings
import os
import json
URL = 'http://www.oreilly.com/pub/sc/osconfeed'
JSON = 'data/osconfeed.json'
def load():if not os.path.exists(JSON): # 如果需要下载就发出提醒msg = 'downloading {} to {}'.format(URL,JSON)warnings.warn(msg)# 两个上下文管理器,分别用于读取和保存远程文件with urlopen(URL) as remote,open(JSON,'wb') as local:local.write(remote.read())with open(JSON,encoding='utf-8') as fp:# 解析json文件,返回python原生对象,在这个数据源中,有几种数据类型:# dict,list,str,intreturn json.load(fp)
if __name__ == '__main__':feed=load()print(sorted(feed['Schedule'].keys()))for key,value in sorted(feed['Schedule'].items()):print('{:3} {}'.format(len(value),key))print(feed['Schedule']['speakers'][-1]['name'])print(feed['Schedule']['speakers'][-1]['serial'])print(feed['Schedule']['events'][-1]['name'])print(feed['Schedule']['events'][40]['speakers'])
# 示例19-5 explore0.py:把一个json对象装换成一个嵌套着FrozenJSON对象,列表.和简单类型的FrozenJSON对象
# 19-5 explore0.py:把一个json对象装换成一个嵌套着FrozenJSON对象,列表.和简单类型的FrozenJSON对象from collections import abc
class FrozenJSON:'''一个只读接口,使用属性表示法访问Json对象'''def __init__(self,mapping):# dict(mapping)确保传入的是字典,或者能被转换成字典的对象# 安全起见,创建一个副本self.__data = dict(mapping)def __getattr__(self, name):'''仅当没有指定名称(name)的属性时,才调用这个方法'''if hasattr(self.__data,name):# 如果name是__data的属性,则返回这个属性return getattr(self.__data,name)else:# 否则,从self.__data中获取name键对应的元素,返回调用FrozenJSON.build# 得到的结果return FrozenJSON.build(self.__data[name])@classmethoddef build(cls,obj):  # 这是一个备选的构造方法if isinstance(obj,abc.Mapping): # 如果obj是映射return cls(obj)elif isinstance(obj,abc.MutableSequence):# 如果是MutableSequence(列表)return [cls.build(item) for item in obj]else: return obj  # 既不是字典也不是列表if __name__ == '__main__':from osconfeed import loadraw_feed = load()# 传入嵌套的字典和列表组成的raw_feed,创建一个FrozenJSON对象feed = FrozenJSON(raw_feed)# FrozenJSON实例能使用属性表示法遍历嵌套的字典print(len(feed.Schedule.speakers))print(sorted(feed.Schedule.keys()))for key,value in sorted(feed.Schedule.items()):print('{:3} {}'.format(len(value),key))print(feed.Schedule.speakers[-1].name)talk = feed.Schedule.events[0]print(type(talk))print(talk.speakers)print(talk.flavor)  # KeyError: 'flavor'
# 19-6 explore1.py:在名称为python关键字的属性后面加上_
# 19-6 explore1.py:在名称为python关键字的属性后面加上_
import keyword
from collections import abc
class FrozenJSON:'''一个只读接口,使用属性表示法访问Json对象'''def __init__(self, mapping):self.__data = {}for key,value in mapping.items():if keyword.iskeyword(key):key += '_'self.__data[key] = valuedef __getattr__(self, name):'''仅当没有指定名称(name)的属性时,才调用这个方法'''if hasattr(self.__data, name):# 如果name是__data的属性,则返回这个属性return getattr(self.__data, name)else:# 否则,从self.__data中获取name键对应的元素,返回调用FrozenJSON.build# 得到的结果return FrozenJSON.build(self.__data[name])@classmethoddef build(cls, obj):  # 这是一个备选的构造方法if isinstance(obj, abc.Mapping):  # 如果obj是映射return cls(obj)elif isinstance(obj, abc.MutableSequence):  # 如果是MutableSequence(列表)return [cls.build(item) for item in obj]else:return obj  # 既不是字典也不是列表if __name__ == '__main__':from osconfeed import loadraw_feed = load()# 传入嵌套的字典和列表组成的raw_feed,创建一个FrozenJSON对象feed = FrozenJSON(raw_feed)# FrozenJSON实例能使用属性表示法遍历嵌套的字典print(len(feed.Schedule.speakers))print(sorted(feed.Schedule.keys()))for key, value in sorted(feed.Schedule.items()):print('{:3} {}'.format(len(value), key))print(feed.Schedule.speakers[-1].name)talk = feed.Schedule.events[0]print(type(talk))print(talk.speakers)print(talk.flavor)  # KeyError: 'flavor'
# 实例19-7 explore2.py:使用__new__方法取代build方法
# 实例19-7 explore2.py:使用__new__方法取代build方法import keyword
from collections import abc
class FrozenJSON:def __new__(cls, arg):if isinstance(arg, abc.Mapping):  # 如果obj是映射return super().__new__(cls)elif isinstance(arg, abc.MutableSequence):  # 如果是MutableSequence(列表)return [cls(item) for item in arg]else:return arg  # 既不是字典也不是列表def __init__(self, mapping):self.__data = {}for key,value in mapping.items():if keyword.iskeyword(key):key += '_'self.__data[key] = valuedef __getattr__(self, name):'''仅当没有指定名称(name)的属性时,才调用这个方法'''if hasattr(self.__data, name):# 如果name是__data的属性,则返回这个属性return getattr(self.__data, name)else:# 否则,从self.__data中获取name键对应的元素,返回调用FrozenJSON.build# 得到的结果return FrozenJSON(self.__data[name])if __name__ == '__main__':from osconfeed import loadraw_feed = load()# 传入嵌套的字典和列表组成的raw_feed,创建一个FrozenJSON对象feed = FrozenJSON(raw_feed)# FrozenJSON实例能使用属性表示法遍历嵌套的字典print(len(feed.Schedule.speakers))print(sorted(feed.Schedule.keys()))for key, value in sorted(feed.Schedule.items()):print('{:3} {}'.format(len(value), key))print(feed.Schedule.speakers[-1].name)talk = feed.Schedule.events[0]print(type(talk))print(talk.speakers)print(talk.flavor)  # KeyError: 'flavor'
# 示例19-9 schedule1.py:访问保存再shelve.Shelf对象里的OSCON数据
# 示例19-9 schedule1.py:访问保存在shelve.Shelf对象里的OSCON数据
import warnings
import osconfeed
DB_NAME = 'data/schedule_db'
CONFERENCE =  'conference.115'
class Record:def __init__(self,**kwargs):# 这是使用关键字参数传入的属性构建实例的常用简便方式self.__dict__.update(kwargs)def load_db(db):raw_data = osconfeed.load()warnings.warn('loading' + DB_NAME)for collection,rec_list in raw_data['Schedule'].items():record_type = collection[:-1]for record in rec_list:key = "{}.{}".format(record_type,record['serial'])record['serial'] = keydb[key] = Record(**record)if __name__ == '__main__':import shelvedb = shelve.open(DB_NAME)if CONFERENCE not in db:load_db(db)speaker = db['speaker.3471']print(speaker)print(speaker.name, speaker.twitter)db.close()
# schedule2.py 使用特性获取链接的记录
# schedule2.py 使用特性获取链接的记录
import warnings
import inspect
import osconfeed
DB_NAME = 'data/schedule2_db'
CONFERENCE =  'conference.115'
class Record:def __init__(self,**kwargs):# 这是使用关键字参数传入的属性构建实例的常用简便方式self.__dict__.update(kwargs)def __eq__(self, other):if isinstance(other,Record):return self.__dict__ == other.__dict__else:return NotImplementedclass MissingDatabaseError(RuntimeError):'''需要数据库,但没有指定数据库时抛出'''class DbRecord(Record):__db = None@staticmethoddef set_db(db):DbRecord.__db = db@staticmethoddef get_db():return DbRecord.__db@classmethoddef fetch(cls,ident):db = cls.get_db()try:return db[ident]except TypeError:if db is None:msg = "database not set;call'{}.set_db(my_db)'"raise MissingDatabaseError(msg.format(cls.__name__))else:raisedef __repr__(self):if hasattr(self,'serial'):cls_name = self.__class__.__name__return '<{} serial = {!r}>'.format(cls_name,self.serial)else:return super().__repr__()# 重要的event类
class Event(DbRecord):@propertydef venue(self):key = 'venue.{}'.format(self.venue_serial)return self.__class__.fetch(key)@propertydef speakers(self):if not hasattr(self,'_speaker_objs'):spkr_serial = self.__dict__['speakers']fetch = self.__class__.fetchself._speaker_objs = [fetch('speaker.{}'.format(key))for key in spkr_serial]return self._speaker_objsdef __repr__(self):if hasattr(self,'name'):cls_name = self.__class__.__name__return  '<{} {!r}>'.format(cls_name,self.name)else:return super().__repr__()
# 重写load_db函数
def load_db(db):raw_data = osconfeed.load()warnings.warn('loading' + DB_NAME)for collection,rec_list in raw_data['Schedule'].items():record_type = collection[:-1]cls_name = record_type.capitalize()cls = globals().get(cls_name,DbRecord)if inspect.isclass(cls) and issubclass(cls,DbRecord):factory = clselse:factory = DbRecordfor record in rec_list:key = "{}.{}".format(record_type,record['serial'])record['serial'] = keydb[key] = factory(**record)
# 19.2.1 LineItem类第一版:表示订单中商品的类
# 示例19-15 bulkfood_v1.py:最简单的LineItem类
class LineItem:def __init__(self,description,weight,price):self.description = descriptionself.weight = weightself.price = pricedef subtotal(self):return self.weight * self.priceif __name__ == '__main__':raisins = LineItem('Golden raisins',10,6.95)print(raisins.subtotal())# 这个简单的类存在的问题raisins.weight = -20  # 无效输入...print(raisins.subtotal())  # 无效输出...
# 示例19-17 bulkfood_v2.py:定义了weight特性的LineItem类
# 示例19-17 bulkfood_v2.py:定义了weight特性的LineItem类
class LineItem:def __init__(self,description,weight,price):self.description = descriptionself.weight = weight  # ①self.price = pricedef subtotal(self):return self.weight * self.price@property  # @property装饰读值方法def weight(self): # 实现特性的方法,其名称与 ①处的公开属性名称一样--weightreturn self.__weight  # 真正的值存储在私有属性__weight中@weight.setter  # 被装饰的读值方法有个setter属性,这个属性也是一个装饰器,这个装饰器把读值方法和设值方法绑定在一起def weight(self,value):if value>0:self.__weight = valueelse:raise ValueError('value must be > 0 ')if __name__ == '__main__':raisins = LineItem('Golden raisins', 10, 6.95)print(raisins.subtotal())raisins.weight = -20  # 抛出异常
# 示例19-17 bulkfood_v2b.py:不使用装饰器
# 示例19-17 bulkfood_v2b.py:不使用装饰器
class LineItem:def __init__(self,description,weight,price):self.description = descriptionself.weight = weight  # ①self.price = pricedef subtotal(self):return self.weight * self.pricedef get_weight(self): # 实现特性的方法,其名称与 ①处的公开属性名称一样--weightreturn self.__weight  # 真正的值存储在私有属性__weight中def set_weight(self,value):if value>0:self.__weight = valueelse:raise ValueError('value must be > 0 ')weight = property(get_weight,set_weight)  # 构建property对象,然后赋值给公开的类属性if __name__ == '__main__':raisins = LineItem('Golden raisins', 10, 6.95)print(raisins.subtotal())raisins.weight = -20  # 抛出异常
# 示例 19-24 bulkfood_v2prop.py:quantity特性工厂函数
# 示例 19-24 bulkfood_v2prop.py:quantity特性工厂函数def quantity(storage_name):def qty_getter(instance):return instance.__dict__[storage_name]def qty_setter(instance,value):if value > 0 :instance.__dict__[storage_name]  = valueelse:raise ValueError('value must be >0')return property(qty_getter,qty_setter)class LineItem:weight = quantity('weight')price = quantity('price')def __init__(self,description,weight,price):self.description = descriptionself.weight = weightself.price = pricedef subtotal(self):return self.weight * self.priceif __name__ == '__main__':nutmeg = LineItem('Moluccan nutmeg',8,13.95)print(nutmeg.weight, nutmeg.price)print(sorted(vars(nutmeg).items()))
# 示例19-26 blackknight.py:定义特性删除方法
# 示例19-26 blackknight.py:定义特性删除方法
class Blackknight:def __init__(self):self.members = ['an arm','another arm','a leg','another leg']self.phrases = ["'Tis but a scratch.","'It's just a flesh wound.","I'm invincible","All right,we'll call it a draw."]@propertydef member(self):print('next member is:')return self.members[0]@member.deleterdef member(self):text = 'BLACK KNIGHT (loses {})\n--{}'print(text.format(self.members.pop(0),self.phrases.pop(0)))if __name__ == '__main__':knight = Blackknight()print(knight.member)del knight.memberdel knight.memberdel knight.memberdel knight.member

35岁学python,也不知道为了啥?

读书笔记:《流畅的Python》第19章 动态属性和特性相关推荐

  1. 读书笔记-流畅的python(1-6章)

    前言:这正是本书的主要目的:着重讲解这门语言的基本惯用法,让你的代码简洁.高效且可读,把你打造成熟练的 Python 程序员. 自己总结学习作为输出,很多为了节省时间只是复制粘贴,不具有广泛意义 第一 ...

  2. 【读书笔记】.NET本质论第四章-Programming with Type(Part Two)

    欢迎阅读本系列其他文章: [读书笔记].NET本质论第一章 The CLR as a Better COM [读书笔记].NET本质论第二章-Components(Part One) [读书笔记].N ...

  3. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第七章 阴影 Shadows

    写在前面的话:因为英语不好,所以看得慢,所以还不如索性按自己的理解简单粗糙翻译一遍,就当是自己的读书笔记了.不对之处甚多,以后理解深刻了,英语好了再回来修改.相信花在本书上的时间和精力是值得的. -- ...

  4. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第五章 着色基础 Shading Basics

    写在前面的话:因为英语不好,所以看得慢,所以还不如索性按自己的理解简单粗糙翻译一遍,就当是自己的读书笔记了.不对之处甚多,以后理解深刻了,英语好了再回来修改.相信花在本书上的时间和精力是值得的. -- ...

  5. 【读书笔记】用Python获取A股行情数据的4种方法

    本人大三在校小学渣一枚,非金融专业,也从来没有过股票期货等金融产品的投资经验,但最近收到了清华出版社赠送的<深入浅出Python量化交易实战>一书,因为平时对数据科学和机器学习都比较感兴趣 ...

  6. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第六章 纹理 Texturing

    写在前面的话:因为英语不好,所以看得慢,所以还不如索性按自己的理解简单粗糙翻译一遍,就当是自己的读书笔记了.不对之处甚多,以后理解深刻了,英语好了再回来修改.相信花在本书上的时间和精力是值得的. -- ...

  7. 读书笔记:精益数据分析 第17-20章

    第17章:阶段三:病毒性 1.进入病毒性阶段后,即可重点关注用户获取与增长,但是同时也要留意产品的黏性. 2.三种传播方式: (1)原生病毒性:根植于产品内部,作为产品使用功能存在. (2)人工病毒性 ...

  8. python基础教程读书笔记_《Python基础教程》 读书笔记 第五章(下)循环语句

    导读热词 5.5.1while循环 x=1 while x<=100: print x x+=1 确保用户输入了名字: name="" while not name: nam ...

  9. 流畅的python第一章_《流畅的Python》第一章学习笔记

    一摞python风格的纸牌from collections import namedtuple Card = namedtuple('Card', ['rank', 'suit']) # 构建只有少数 ...

最新文章

  1. c语言结点初始化,C语言双向链表简单实现及图示(初始化/插入节点/删除节点)...
  2. golang atomic 32位机器问题
  3. android盒子模拟器,emubox模拟器盒子
  4. 空间金字塔匹配Spatial Pyramid Matching 小结
  5. 微电网日前优化调度 。算例有代码(0)
  6. 未找到要求的 from 关键字_性能优化|这恐怕是解释Explain关键字最全的一篇文章
  7. javascript 页面跳转大总结
  8. NOIP2017 列队——动态开点线段树
  9. git配置取消代理_「高手」如何优雅的解决 git 超时
  10. 传智播客 tcp长连接和短连接 学习笔记
  11. linux命令之拒绝服务-关机重启shutdown-init0-6删库(滑稽脸)
  12. Java—核心技术类的封装、继承与多态
  13. The DAO事件始末
  14. 我爱Ruby的三十七个理由
  15. 计蒜客 联想专卖店大促销
  16. 话说软件破解:道高一尺魔高一丈
  17. 美国NBC电视台社论 中文版
  18. P4606 [SDOI2018]战略游戏
  19. 如何确定复杂句中同位语的对应词(对应名词)?
  20. Linux下可以给视频换脸吗,视频AI换脸软件教程 看这里

热门文章

  1. 做了一个仿吃鸡游戏,可多人联网,算是学习总结。
  2. 网卡属性全是英文怎么搞
  3. 大数据专业在大学需要考什么证_大学可以考哪些证书呢?超高含金量的考证规划,安排!...
  4. ol中闪烁点动画的实现
  5. 启动项目报错 Failed to bind properties under
  6. 【Linux系列】什么是LVM
  7. 面试题:打印螺旋数字
  8. Linux连接redis数据库
  9. configure: error: C++ preprocessor /lib/cpp fails sanity check
  10. 初学3D制作,先学C4D还是Blender?