python学习之面向对象高级特性和魔术方法(python学习之,python魔术方法,编程语言)

时间:2024-05-02 22:21:42 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

01_property商品应用.py

分页显示是一种非常常见的浏览和显示大量数据的方法,属于web编程中最常处理的事件之一。

类属性应用需求: 对于京东商城中显示电脑主机的列表页面,每次请求不可能把数据库
中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求
数据时就要显示的指定获取从第start条到第end条的所有数据 这个分页的功能包括:
• 根据用户请求的当前页和总数据条数计算出 start 和 end
• 根据start 和 end 去数据库中请求数据
• 是否有上一页has_prev、下一页has_next
• 上一页prev、下一页next
• 总页数pages, 数据总条数total、当前页信息items

"""

class Pagintor(object): """实现商品分页的类""" def __init__(self, objects_list, page=1, per_page=5): """ :param objects_list: 商品列表 :param page: 当前需要显示的页码信息 :param per_page: 每页显示的数据个数 """ self.objects_list = objects_list self.page = page self.per_page = per_page @property def start(self): return (self.page - 1) * self.per_page @property def end(self): return self.page * self.per_page @property def total(self): """ 数据总条数total :return: """ return len(self.objects_list) @property def pages(self): """ 总页数pages if 总商品数量%每页显示数量==0: 刚好当前页显示满 else: 好友多与的部分, 在计算的结果上面加1 self.total = 5 pages=1 self.total = 6 pages=2 :return: """ result = self.total // self.per_page if self.total % self.per_page == 0: return result else: return result + 1 @property def has_next(self): return True if 0 < self.page + 1 <= self.pages else False @property def next(self): next_page = self.page - 1 next_start = (next_page - 1) * self.per_page next_end = self.page * self.per_page return self.objects_list[next_start:next_end] @property def has_prev(self): return True if 0 < self.page - 1 <= self.pages else False @property def prev(self): prev_page = self.page - 1 prev_start = (prev_page - 1) * self.per_page prev_end = self.page * self.per_page return self.objects_list[prev_start:prev_end] @property def items(self): """ 当前页信息items :return: """ return self.objects_list[self.start:self.end]if __name__ == '__main__': # 应用场景二: 某一个属性不能直接返回, 需要计算的, 可以通过property属性实现 goods = ["电脑" + str(i) for i in range(5)] #需求: 显示第三页时, 开始的索引是? 结束的索引为多少? pagintor = Pagintor(goods, page=1, per_page=6) print("第1页的商品信息为: ", goods[pagintor.start:pagintor.end]) print("是否有上一页?", pagintor.has_prev) print("总页数?", pagintor.pages)"""

02_property通过函数的方式实现类属性.py

class Person(object): def __init__(self, name, age): self.name = name self.__age = age #私有属性 @property def is_age_vaild(self): return 0 < self.__age <= 150 def get_age(self): if self.is_age_vaild: return self.__age else: raise Exception("年龄不合法") def set_age(self, age): if self.is_age_vaild: self.__age = age else: raise Exception("年龄不合法") def del_age(self): print("年龄属性删除......") #类属性 即:在类中定义值为property对象的类属性 age = property(fget=get_age, fset=set_age, fdel=del_age)if __name__ == '__main__': p1 = Person("张三", 30) print(p1.age) p1.age = 31 print(p1.age) del p1.age

03_property通过函数的方式实现类属性.py

class Person(object): def __init__(self, name, age, score): self.name = name self.__age = age # 私有属性 self.__score = score @property def score(self): return self.__score @score.setter def score(self, score): self.__score = score @property def is_age_vaild(self): return 0 < self.__age <= 150 @property # 获取age属性时执行的内容 def age(self): if self.is_age_vaild: return self.__age else: raise Exception("年龄不合法") @age.setter # 设置age属性时执行的内容 def age(self, age): if self.is_age_vaild: self.__age = age else: raise Exception("年龄不合法") @age.deleter # 删除age属性时执行的内容 def age(self): print("年龄属性删除......")if __name__ == '__main__': p1 = Person("张三", 30, 100) print(p1.age) # 获取年龄(), 执行@property def age(self): p1.age = 31 # 设置年龄, age=31 print(p1.age) del p1.age # 删除年龄属性

05_装饰器实现单例模式.py

from functools import wrapsdef singleton(cls): """ 实现单例模式的装饰器 思路: 当实例化对象时, 判断该类是否实例化过对象。 - 如果是, 返回之前实例化的对象。 - 如果不是, 实例化第一个对象, 并将实例化后的对象存储起来(缓存)。 """ instances = {} # {'Person': obj} @wraps(cls) def wrapper(*args, **kwargs): name = cls.__name__ if instances.get(name): # 直接返回缓存中的对象 return instances.get(name) else: # 第一次实例化对象 obj = cls(*args, **kwargs) #类名作为key值, 对象作为value值, 存储到instances字典中. instances[name] = obj return obj return wrapper@singletonclass Person(object): passif __name__ == '__main__': p1 = Person() p2 = Person() #面试题目: ==和is有什么区别? print("单例模式是否成功?", p1 is p2)

魔术方法
在Python中,所有用""包起来的方法,都称为【魔术方法】(eg: len, init__)。
魔术方法一般是为了让显示器调用的,你自己并不需要调用它们。
特殊属性:
python学习之面向对象高级特性和魔术方法
dir
查看属性
返回类或者对象的所有成员名称列表。dir() 函数就是调用dir()。
1). 如果dir([obj]) 参数obj包含方法 dir(),该方法将被调用。
2). 如果Obj 不包含 dir(),该方法将最大限度收集属性信息
python 中new , init , call的区别?
1). new的功能是在生成对象之前执行的内容,接受的参数是cls 类, 负责对象的创建
2). init的功能是在对象生成之后执行的内容, 接受的参数是self 对象, 负责对象的初始化
3). call的功能是在调用对象时执行的内容, 可以模拟函数的行为

06_new方法实现单例模式改进版.py

from datetime import dateclass Person(object): def __new__(cls, *args, **kwargs): print("判断当前类是否拥有instance属性?", hasattr(cls, 'instance')) if not hasattr(cls, 'instance'): cls.instance = super(Person, cls).__new__(cls) return cls.instance def __init__(self, name): self.name = namep1 = Person("张三")p2 = Person("张xxx")print("单例模式是否成功? ", p1 is p2)

06_通过new方法实现单例模式.py

class Person(object): # 1). 设置类属性, 存储已经创建好的对象。 _instance = None def __new__(cls, *args, **kwargs): print("new方法在实例化对象之前执行.....返回对象本身") #2). 判断是否已经实例化对象? if cls._instance: return cls._instance else: self = object.__new__(cls) cls._instance = self #返回父类object的new方法创建的对象..... return self def __init__(self): print("构造方法实例化对象之后执行......")if __name__ == '__main__': p1 = Person() p2 = Person() print(p1, p2)"""

07_call.py

1). new的功能是在生成对象之前执行的内容,接受的参数是cls 类, 负责对象的创建
2). init的功能是在对象生成之后执行的内容, 接受的参数是self 对象, 负责对象的初始化
3). call的功能是在调用对象时执行的内容, 可以模拟函数的行为.
"""

class Person(object): def __new__(cls): print("__new__") return object.__new__(cls) def __init__(self): print("__init__") def __call__(self, *args, **kwargs): print('__call__') def __del__(self): # 析构方法: 当对象被删除或者从内存释放时自动执行 print("__del__")p1 = Person()p1()

08_call魔术方法实现缓存.py

from functools import lru_cacheclass Fib(object): @lru_cache(maxsize=1000) def __call__(self, n): if n in (1, 2): return 1 else: return self(n-1) + self(n-2)fib = Fib()print(fib(100)) # 1 1 2 3 5 8"""

可视化
类型判断要使用type或isinstance, 不能通过判断print输出是否带引号来判断输出值的类型。
1). str()与repr()都是python中的内置函数,是直接用来格式化字符串的函数。
2). 当使用内置函数str(obj)时, 自动执行obj.str()魔术方法。
3). 当使用内置函数repr(obj)时, 自动执行obj.repr()魔术方法。
4). 当str魔术方法不存在时, 自动执行repr()魔术方法的内容。
类型转换
python学习之面向对象高级特性和魔术方法

09_可视化魔术方法.py

class Person(object): def __init__(self, name, age): self.name = name self.age = age def __int__(self): return int(self.age) #def __str__(self): #return 'Person<%s>' %(self.name) def __repr__(self): return 'Person<%s>' %(self.name)p1 = Person("fentiao", '100')print(p1)print(int(p1))

索引与切片
拓展小知识: slice() 函数实现切片对象,主要用在切片操作函数里的参数传递。
索引&切片魔术方法:
setitem:当属性被以索引、切片方式赋值的时候会调用该方法
getitem:一般如果想使用索引、切片访问元素时,就可以在类中定义这个方法
delitem:当使用索引、切片删除属性时调用该方法

10_魔术方法实现索引和切片.py

class Student(object): def __init__(self, name, scores): self.name = name self.scores = scores def __getitem__(self, index): """实现获取索引和切片值的魔术方法""" print(index) return self.scores[index] def __setitem__(self, index, value): """实现修改/设置索引和切片值的魔术方法""" self.scores[index] = value def __delitem__(self, index): del self.scores[index] def __mul__(self, other): """重复操作""" return self.scores * other def __add__(self, other): """连接操作, 传入的时对象""" return [ item[0]+item[1] for item in zip(self.scores, other.scores)] def __contains__(self, item): """成员操作符""" return item in self.scores def __iter__(self): # iter可以将可迭代对象转换成迭代器(可以调用next方法的) return iter(self.scores)stu1 = Student("张三", [100, 90, 100])stu2 = Student("里斯", [100, 80, 100])#1). 索引和切片的测试#print(stu1[1:]) # 获取索引/切片值#stu1[1:] = (80, 80) # 设置索引/切片对应的value值#print(stu1.scores)#del stu1[1:] # 删除索引/切片值#print(stu1.scores)##2). 连接、重复和成员操作符#print(stu1*3)#print(stu1 + stu2)#print(150 in stu1)for item in stu1: print(item)

with语句安全上下文
with语句操作的对象必须是上下文管理器。那么,到底什么是上下文管理器呢?
1). 简单的理解,拥有 enter() 和 exit() 方法的对象就是上下文管理器。
enter(self):进入上下文管理器自动调用的方法,在 with 执行之前执行。如果 有 as子句,该
方法的返回值被赋值给 as 子句后的变量;该方法可以返回多个值。
exit(self, exc_type, exc_value, exc_traceback):退出上下文管理器自动调用的方法。在
with 执行之后执行(不管有无异常)。
2). 当 with as 操作上下文管理器时,就会在执行语句体之前,先执行上下文管理器的 enter() 方法,
然后再执行语句体,最后执行 exit() 方法。
构建上下文管理器,常见的有 2 种方式:基于类实现和基于生成器实现。
方法一: 装饰器 contextlib.contextmanager,来定义自己所需的基于生成器的上下文管理器
方法二: 基于类的上下文管理器: 只要一个类实现了 enter() 和 exit() 这 2 个方
法,程序就可以使用 with as 语句来管理它

11_魔术方法实现with语句上下文管理器.py

class Connect(object): def __init__(self, filename): self.filename = filename def __enter__(self): self.f = open(self.filename) return self.f def __exit__(self, exc_type, exc_val, exc_tb): print('with语句执行之后......') self.f.close()#Connect就是上下文管理器。 拥有 __enter__() 和 __exit__() 方法的对象就是上下文管理器with Connect('/etc/passwd') as conn: pass

12_装饰器实现上下文管理器的方法.py

import contextlibimport tempfileimport shutil@contextlib.contextmanagerdef make_temp_dir(): try: tmp_dir = tempfile.mkdtemp() yield tmp_dir finally: shutil.rmtree(tmp_dir)with make_temp_dir() as f: pass

13_比较大小.py

class Int(object): def __init__(self, number, weight): self.number = number self.weight = weight def __gt__(self, other): """判断大于的魔术方法""" return self.number * self.weight > other.number * other.weight def __ge__(self, other): """判断大于等于的魔术方法""" return self.number * self.weight >= other.number * other.weight def __eq__(self, other): """判断等于的魔术方法""" return self.number * self.weight == other.number * other.weighti1 = Int(20, 3)i2 = Int(20, 3)print(i1 > i2)print(i1 < i2)print(i1 >= i2)print(i1 == i2)print(i1 != i2)

01_call魔术方法实现类装饰器.py

from functools import wrapsimport timedef timeit(unit='s'): def wrapper1(fun): # fun=add @wraps(fun) def wrapper(*args, **kwargs): if unit == 's': start_time = time.time() result = fun(*args, **kwargs) # add(1, 2) result=3 end_time = time.time() print("%s函数运行时间为%.2f s" %(fun.__name__, end_time-start_time)) return result else: print("当前功能不支持......") return wrapper return wrapper1#类装饰器: 装饰器需要传递的参数通过__init__传递进入.被装饰函数执行的内容在__call__魔术方法中编写。class TimeIt(object): def __init__(self, unit='s'): self.unit = unit def __call__(self,fun): @wraps(fun) def wrapper(*args, **kwargs): if self.unit == 's': start_time = time.time() result = fun(*args, **kwargs) #add(1, 2) result=3 end_time = time.time() print("%s函数运行时间为%.2f s" % (fun.__name__, end_time - start_time)) return result else: print("当前功能不支持......") return wrapper#@timeit(unit='s') #@wrapper1 ==> add = wrapper1(add) ===> add =wrapper#def add(num1, num2):#time.sleep(0.333)#return num1 + num2"""@TimeIt(unit='h') #1). TimeIt_obj = TimeIt(unit='h') #2). @TimeIt_obj#3). add=TimeIt_obj(add)#4). add = wrapper"""@TimeIt(unit='s')def add(num1, num2): time.sleep(0.333) return num1 + num2#add(1, 2) ==> wrapper(1, 2)add(1, 2)

02_call魔术方法实现偏函数.py

from functools import partialmax_100 = partial(max,10, 100) # 返回对象print(max_100(1, 2, 3)) # 100"""

03_基于call魔术方法和filter实现文件过滤器.py

from wtforms import StringField,SubmitFieldimport os#作为基类/父类class FileAcceptor(object): def __init__(self, accepted_extensions): """ eg: ['.png', '.jpg'] :param accepted_extensions: 可以接受的扩展名 """ self.accepted_extensions = accepted_extensions def __call__(self, filename): """ eg: hello.jpg :param filename: 需要判断的文件名 :return: """ #base = 'hello', ext='.jpg' base, ext = os.path.splitext(filename) return ext in self.accepted_extensions#子类class ImageFileAcceptor(FileAcceptor): def __init__(self): image_ext = ('.jpg', '.jepg', '.png') super(ImageFileAcceptor, self).__init__(image_ext)#子类class ExcelFileAcceptor(FileAcceptor): def __init__(self): image_ext = ('.xls', '.xlsx') super(ExcelFileAcceptor, self).__init__(image_ext)if __name__ == '__main__': filenames = [ 'hello.jpg', 'hello.xls', 'hello.txt' ] """ 1). ImageFileAcceptor() 实例化对象, 执行__new__和__init__魔术方法。 2). imagefileacceptor_obj 3). imagefileacceptor_obj('hello.jpg') True 3). imagefileacceptor_obj('hello.xls') False 3). imagefileacceptor_obj('hello.txt') False 4). ['hello.jpg'] """ images_file = filter(ImageFileAcceptor(), filenames) excels_file = filter(ExcelFileAcceptor(), filenames) print(list(images_file)) print(list(excels_file))

04_通过分支语句动态的创建类.py

def create_class(name): if name == 'foo': class Foo(object): pass return Foo else: class Bar(object): pass return Barcls = create_class(name='foo1')print(cls.__name__)

05_通过type动态地创建类.py

#type函数语法:#type(类名, 父类名称的元组, 属性信息)#class Person(object):#country= 'China'def hello(self): print("hello")Person = type('Person',(object, ), {'country':'China', 'hello':hello})p1 = Person()print(p1.country)p1.hello()

魔术方法汇总
基本的魔法方法
有关属性的魔术方法
比较操作符
算数运算符
反运算
增量赋值运算
一元操作符
类型转换
上下文管理(with 语句)
容器类型
python学习之面向对象高级特性和魔术方法

元类
类也是对象
Python一切皆对象
Linux一切皆文件
元类是类的类,是类的模板
元类的实例为类,正如类的实例为对象。
类的本质是对象, 于是可以对类做如下的操作:

class Singleton(type): type(name, bases, attrs) 自定义元类实现单例模式, 父类是type #所有类和实例化对象之间的关系; eg: {'Person': Pseron()} cache = {} #1). 为什么是__call__魔术方法? def __call__(cls): #判断类是否已经实例化, 如果没有, 实例化后存储到缓存中。 最后将缓存的信息返回给用户。 if cls not in cls.cache: cls.cache[cls] = super(Singleton, cls).__call__() return cls.cache[cls]#type('Pseron', (), {})#创建以各类Person, 指定创建Person类的类(元类)是type.#2. metaclass是在做什么? 指定元类为Singleton。class Person(object, metaclass=Singleton): # Person = Singleton.__new__(Person, (objects, ), {}) pass#Person是Singleton元类实例化出的对象, Person()就是对象(), 执行Singleton.__call__魔术方法.p1 = Person()p2 = Person()print(p1, p2)#99%情况不需要自己自定义元类。

抽象基类
抽象基类有两个特点:
1.规定继承类必须具有抽象基类指定的方法
2.抽象基类无法实例化
基于上述两个特点,抽象基类主要用于接口设计
实现抽象基类可以使用内置的abc模块

07_抽象基类.py

import abcclass Human(metaclass=abc.ABCMeta): """基类, 定义一个抽象类""" @abc.abstractmethod def introduce(self): print("introduce.....") @abc.abstractmethod def hello(self): print('hello')class Person(Human): # 1).规定继承类必须具有抽象基类指定的方法 def introduce(self): print('person') def hello(self): print('person hello')#2). 抽象基类无法实例化#h = Human()p = Person()p.introduce()p.hello()

动态语言与静态语言的不同?

import timefrom datetime import date#d = date.today()#print("对象类型: ", type(d)) # <class 'datetime.date'>#print("判断是否有year这个属性?", hasattr(d, 'year')) # True#print("判断是否有time这个属性?", hasattr(d, 'time')) # False##setattr(d, 'time', '10:10:10') # 报错class Date(object): # __slots__ 来限制该对象能添加的属性信息 __slots__ = '__year', '__month', '__day' def __new__(cls, year, month, day): self = object.__new__(cls) self.__year = year self.__month = month self.__day = day return self @property def year(self): return self.__year @property def month(self): return self.__month @property def day(self): return self.__day @classmethod def today(cls): time_t = time.localtime() return cls(time_t.tm_year, time_t.tm_mon, time_t.tm_mday) def __str__(self): return '%s-%s-%s' %(self.__year, self.__month, self.__day)d = Date(2019, 10, 10)print("对象类型: ", type(d)) # <class 'datetime.date'>print("判断是否有year这个属性?", hasattr(d, 'year')) # Trueprint("判断是否有time这个属性?", hasattr(d, 'time')) # False#setattr(d, 'time', '10:10:10') # Error#print('time:', getattr(d, 'time')) # Errorprint(Date.today())

09_垃圾回收机制.py

#1). 整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池,
#避免为整数频繁申请和销毁内存空间。

#2). Python对小整数的定义是[-5,257)>>> a = 1>>> id(a)139883638752032>>> b = 1>>> id(b)139883638752032>>> c = 257>>> d = 257>>> id(c), id(d)(139883633580400, 139883633580432)>>> e=-5;f=-5>>> id(e), id(f)(139883638751840, 139883638751840)#********************************2. 字符串驻留机制 ********************************#1). string interning(字符串驻留): 它通过维护一个字符串常量池(string intern pool),#从而试图只保存唯一的字符串对象,达到既高效又节省内存地处理字符串的目的。>>> a = 'hello'>>> b = 'hello'>>> id(a), id(b)(139883511138480, 139883511138480)>>> c = 'pythonchjdshfcejhfkjrehfkjrehfkjrehfregjrkhgkjrg'>>> d = 'pythonchjdshfcejhfkjrehfkjrehfkjrehfregjrkhgkjrg'>>> id(c),id(d)(139883633099360, 139883633099360)#2). 字符串(含有空格),不可修改,没开启intern机制,不共用对象,引用计数为0,销毁。>>> a = 'a b'>>> b = 'a b'>>> id(a), id(b)(139883511138608, 139883511138544)

10_引用计数机制.py

#导致引用计数+1的情况>>> #1). 对象被创建,例如a=23...>>> name = 'fentiao'>>>>>> #2). 对象被作为参数,传入到一个函数中...>>> import sys>>> sys.getrefcount(name)2>>> #3). 对象被引用,例如b=a...>>> cat_name = name>>> sys.getrefcount(name)3>>> #4). 对象作为一个元素,存储在容器中,例如list1=[a,a]...>>> l = [name, 'hello', 'python']>>> sys.getrefcount(name)4#***************************导致引用计数-1的情况*************************>>> #1). 对象的别名被显式销毁,例如del a...>>> del cat_name>>> sys.getrefcount(name)3>>> #2). 对象的别名被赋予新的对象,例如a=24>>> name1 = name>>> sys.getrefcount(name)4>>> name1 = 'hello'>>> sys.getrefcount(name)3>>> #4). 对象所在的容器被销毁,或从容器中删除对象...>>> l['fentiao', 'hello', 'python']>>> del l[0]>>> sys.getrefcount(name)2#****************************gc模块使用***********************************#1). 分代回收的频率>>> gc.get_threshold()(700, 10, 10)>>>gc.set_threshold(700, 90, 90)KeyboardInterrupt#2). 垃圾回收机制是否开启>>>gc.isenabled()True>>>gc.disable()>>>gc.isenabled()False>>> gc.enable()>>>gc.isenabled()True
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:python学习之面向对象高级特性和魔术方法的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Python综合应用:手把手教你用字符打印一张怀旧风格的照片下一篇:

9 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18