getattr和getattribute魔法函数
from datetime import date,datetime
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
def __getattr__(self,item):
print("not find attr")
def __getattribute__(self,item):
return "juran"
if __name__ == "__main__":
user = User("juran",date(year=1990,month=1,day=1))
print(user.age)
属性描述符
class User:
def __init__(self,age):
self.age = age
def get_age(self):
return (str(self.age) + '岁')
def set_age(self,age):
if not isinstance(age,int):
raise TypeError('Type Error')
self.age = age
from datetime import date,datetime
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
def __getattr__(self,item):
print("not find attr")
def __getattribute__(self,item):
return "juran"
if __name__ == "__main__":
user = User("juran",date(year=1990,month=1,day=1))
print(user.age)
class User:
def __init__(self,age):
self.age = age
def get_age(self):
return (str(self.age) + '岁')
def set_age(self,age):
if not isinstance(age,int):
raise TypeError('Type Error')
self.age = age
如果User类中有多个属性都需要判断,那么就需要写多个方法,这些方法怎么复用呢?这个时候就要用到属性描述符
属性描述符,只要实现了__get__,__set__,__delete__任何一个方法,就被称为属性描述符
属性查找顺序
user = User(), 那么user.age 顺序如下:
1 如果"age"是出现在User或其基类的__dict__中, 且age是data descriptor,那么调用其__get__方法, 否则
2 如果"age"出现在user的__dict__中, 那么直接返回 obj.__dict__['age'],否则
3 如果"age"出现在User或其基类的__dict__中
3.1 如果age是non-data descriptor,那么调用其__get__方法, 否则
3.2 返回 __dict__['age']
4 如果User有__getattr__方法,调用__getattr__方法,否则
5 抛出AttributeError
自定义元类
user = User(), 那么user.age 顺序如下:
1 如果"age"是出现在User或其基类的__dict__中, 且age是data descriptor,那么调用其__get__方法, 否则
2 如果"age"出现在user的__dict__中, 那么直接返回 obj.__dict__['age'],否则
3 如果"age"出现在User或其基类的__dict__中
3.1 如果age是non-data descriptor,那么调用其__get__方法, 否则
3.2 返回 __dict__['age']
4 如果User有__getattr__方法,调用__getattr__方法,否则
5 抛出AttributeError
动态创建类
def create_class(name):
if name == "user":
class User:
def __str__(self):
return "user"
return User
elif name == "student":
class Student:
def __str__(self):
return "Student"
return Student
if __name__ == "__main__":
myclass = create_class('user')
obj = myclass()
print(obj)
print(type(obj))
使用type创建类
type还可以动态的创建类,type(类名,由父类组成的元组,包含属性的字典)
* 第一个参数:name表示类名称,字符串类型
* 第二个参数:bases表示继承对象(父类),元组类型,单元素使用逗号
* 第三个参数:attr表示属性,这里可以填写类属性、类方式、静态方法,采用字典格式,key为属性名,value为属性值
* metaclass属性:如果一个类中定义了metalass = xxx,Python就会用元类的方式来创建类
属性描述符
# class User(object):
# def __init__(self, age, name):
# self.age = age
# self.name = name
#
# def get_age(self):
# return self.age
#
# def set_age(self, age):
# if not isinstance(age, int):
# raise TypeError('type error')
# self.age = age
# 属性描述符 __get__ __set__ __delete__
# Django
class IntField(object):
"""
数据描述符
"""
def __get__(self, instance, owner):
print("__get__")
# print(instance)
return self.values
def __set__(self, instance, value):
print("__set__")
# print(instance)
# print(value)
if not isinstance(value, int):
raise ValueError('Value Error')
self.values = value
def __delete__(self, instance):
pass
class NoneDataIntField:
def __get__(self, instance, owner):
pass
class User:
age = IntField()
# age = 19
user = User()
user.age = 30
user.__dict__['age'] = 18
print(user.age)
迭代器
迭代的概念:
- 迭代:通过for循环遍历对象的每一个元素的过程。
- Python的for语法功能非常强大,可以遍历任何可迭代的对象。
- 在Python中,list/tuple/string/dict/set/bytes都是可以迭代的数据类型。
# 迭代器是什么?
- 迭代器是一种可以被遍历的对象,并且能作用于next()函数。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
- 迭代器只能往后遍历不能回溯,不像列表,你随时可以取后面的数据,也可以返回头取前面的数据。
from collections import Iterator, Iterable
# print(isinstance(list(), Iterable)) # True
# print(isinstance(list(), Iterator)) # False
# iter next
l = [1, 2, 3, 4]
it = iter(l)
# print(it)
# print(next(it))
# print(next(it))
# print(next(it))
print(next(it), '-')
for i in it:
print(i)
生成器
- 有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的
### 生成器如何读取大文件
文件300G,文件比较特殊,一行 分隔符 {|}
def readlines(f,newline):
buf = ""
while True:
while newline in buf:
pos = buf.index(newline)
yield buf[:pos]
buf = buf[pos + len(newline):]
chunk = f.read(4096*10)
if not chunk:
yield buf
break
buf += chunk
with open('demo.txt') as f:
for line in readlines(f,"{|}"):
print(line)
type还可以动态的创建类,type(类名,由父类组成的元组,包含属性的字典)
* 第一个参数:name表示类名称,字符串类型
* 第二个参数:bases表示继承对象(父类),元组类型,单元素使用逗号
* 第三个参数:attr表示属性,这里可以填写类属性、类方式、静态方法,采用字典格式,key为属性名,value为属性值
* metaclass属性:如果一个类中定义了metalass = xxx,Python就会用元类的方式来创建类
# class User(object):
# def __init__(self, age, name):
# self.age = age
# self.name = name
#
# def get_age(self):
# return self.age
#
# def set_age(self, age):
# if not isinstance(age, int):
# raise TypeError('type error')
# self.age = age
# 属性描述符 __get__ __set__ __delete__
# Django
class IntField(object):
"""
数据描述符
"""
def __get__(self, instance, owner):
print("__get__")
# print(instance)
return self.values
def __set__(self, instance, value):
print("__set__")
# print(instance)
# print(value)
if not isinstance(value, int):
raise ValueError('Value Error')
self.values = value
def __delete__(self, instance):
pass
class NoneDataIntField:
def __get__(self, instance, owner):
pass
class User:
age = IntField()
# age = 19
user = User()
user.age = 30
user.__dict__['age'] = 18
print(user.age)
迭代的概念:
- 迭代:通过for循环遍历对象的每一个元素的过程。
- Python的for语法功能非常强大,可以遍历任何可迭代的对象。
- 在Python中,list/tuple/string/dict/set/bytes都是可以迭代的数据类型。
# 迭代器是什么?
- 迭代器是一种可以被遍历的对象,并且能作用于next()函数。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
- 迭代器只能往后遍历不能回溯,不像列表,你随时可以取后面的数据,也可以返回头取前面的数据。
from collections import Iterator, Iterable
# print(isinstance(list(), Iterable)) # True
# print(isinstance(list(), Iterator)) # False
# iter next
l = [1, 2, 3, 4]
it = iter(l)
# print(it)
# print(next(it))
# print(next(it))
# print(next(it))
print(next(it), '-')
for i in it:
print(i)
- 有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的
### 生成器如何读取大文件
文件300G,文件比较特殊,一行 分隔符 {|}
def readlines(f,newline):
buf = ""
while True:
while newline in buf:
pos = buf.index(newline)
yield buf[:pos]
buf = buf[pos + len(newline):]
chunk = f.read(4096*10)
if not chunk:
yield buf
break
buf += chunk
with open('demo.txt') as f:
for line in readlines(f,"{|}"):
print(line)