python入门开发学习笔记之内置方法

Python二级笔记(18,19合集知识点篇) 知识点: 1,软件测试的目的是发现程序中的错误。调试是作为成功测试的后过而出现的步骤,也就是,调试是在测试发现错误之后排除错误的过程。软件调试的任务是诊断和改成程序中的错误。 2,深度等于控制的层数 3,概念模型,着重于客户世界复杂事务的描述及其它们内在联系的刻画,与具体的DBMS(数据库管理系统)无关。 4,python运算符优先级 5,函数的参数在定义时可以指定默认值,当函数被调用时,如果没有传入对应的参数值,则使用函数定义时的默认值替代。 在Python中,函数调用时,参数传递的主要方 阅读详情

内置方法

一 isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

class Foo(object):
    pass
obj = Foo()
isinstance(obj, Foo)

issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo(object):
    pass
class Bar(Foo):
    pass
issubclass(Bar, Foo)

二 反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数 下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

hasattr(object,name)

判断object中有没有一个name字符串对应的方法或属性

getattr(object, name, default=None)

def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value

    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass

setattr(x, y, v)

def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.

    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass

delattr(x, y)

def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.

    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass

四个方法的使用演示

class BlackMedium:
    feature='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_house(self):
        print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
    def rent_house(self):
        print('%s 黑中介租房子啦,傻逼才租呢' %self.name)

b1=BlackMedium('万成置地','回龙观天露园')

#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))

#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()

# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))

#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))

#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错

print(b1.__dict__)

类也是对象

class Foo(object):

    staticField = "old boy"

    def __init__(self):
        self.name = 'wupeiqi'

    def func(self):
        return 'func'

    @staticmethod
    def bar():
        return 'bar'

print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')

反射当前模块成员


#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys

def s1():
    print 's1'

def s2():
    print 's2'

this_module = sys.modules[__name__]

hasattr(this_module, 's1')
getattr(this_module, 's2')

导入其他模块,利用反射查找该模块是否存在某个方法

module_test.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
程序目录:
    module_test.py
    index.py

当前文件:
    index.py
"""

import module_test as obj

#obj.test()

print(hasattr(obj,'test'))

getattr(obj,'test')()

3 为什么用反射之反射的好处

好处一:实现可插拔机制

有俩程序员,一个lili,一个是egon,lili在写程序的时候需要用到egon所写的类,但是egon去跟女朋友度蜜月去了,还没有完成他写的类,lili想到了反射,使用了反射机制lili可以继续完成自己的代码,等egon度蜜月回来后再继续完成类的定义并且去实现lili想要的功能。

总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

egon还没有实现全部功能

class FtpClient:
    'ftp客户端,但是还么有实现具体的功能'
    def __init__(self,addr):
        print('正在连接服务器[%s]' %addr)
        self.addr=addr

不影响lili的代码编写

#from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
    func_get=getattr(f1,'get')
    func_get()
else:
    print('---->不存在此方法')
    print('处理其他的逻辑')

好处二:动态导入模块(基于反射当前模块成员)

[图片上传失败…(image-23be58-1649403153183)]

三 setattr,delattr,getattr

三者的用法演示

class Foo:
    x=1
    def __init__(self,y):
        self.y=y

    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')

    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #这就无限递归了,你好好想想
        # self.__dict__[key]=value #应该使用它

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)

#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)

#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)

#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

四 二次加工标准类型(包装)

包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)

二次加工标准类型(基于继承实现)

class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
    def append(self, p_object):
        ' 派生自己的append:加上类型检查'
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        super().append(p_object)

    @property
    def mid(self):
        '新增自己的属性'
        index=len(self)//2
        return self[index]

l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型

print(l.mid)

#其余的方法都继承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)

练习(clear加权限限制)

class List(list):
    def __init__(self,item,tag=False):
        super().__init__(item)
        self.tag=tag
    def append(self, p_object):
        if not isinstance(p_object,str):
            raise TypeError
        super().append(p_object)
    def clear(self):
        if not self.tag:
            raise PermissionError
        super().clear()

l=List([1,2,3],False)
print(l)
print(l.tag)

l.append('saf')
print(l)

# l.clear() #异常

l.tag=True
l.clear()
```py
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

实现授权的关键点就是覆盖\_\_getattr\_\_方法

**授权示范一**
```py
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        self.file=open(filename,mode,encoding=encoding)
    def write(self,line):
        t=time.strftime('%Y-%m-%d %T')
        self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):
        return getattr(self.file,item)

f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()

授权示范二

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我们来加上b模式支持
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        if 'b' in mode:
            self.file=open(filename,mode)
        else:
            self.file=open(filename,mode,encoding=encoding)
        self.filename=filename
        self.mode=mode
        self.encoding=encoding

    def write(self,line):
        if 'b' in self.mode:
            if not isinstance(line,bytes):
                raise TypeError('must be bytes')
        self.file.write(line)

    def __getattr__(self, item):
        return getattr(self.file,item)

    def __str__(self):
        if 'b' in self.mode:
            res="<_io.BufferedReader name='%s'>" %self.filename
        else:
            res="<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" %(self.filename,self.mode,self.encoding)
        return res
f1=FileHandle('b.txt','wb')
# f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了,简单,大气
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()

练习题(授权)

#练习一
class List:
    def __init__(self,seq):
        self.seq=seq

    def append(self, p_object):
        ' 派生自己的append加上类型检查,覆盖原有的append'
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        self.seq.append(p_object)

    @property
    def mid(self):
        '新增自己的方法'
        index=len(self.seq)//2
        return self.seq[index]

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)

l=List([1,2,3])
print(l)
l.append(4)
print(l)
# l.append('3333333') #报错,必须为int类型

print(l.mid)

#基于授权,获得insert方法
l.insert(0,-123)
print(l)

#练习二
class List:
    def __init__(self,seq,permission=False):
        self.seq=seq
        self.permission=permission
    def clear(self):
        if not self.permission:
            raise PermissionError('not allow the operation')
        self.seq.clear()

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)
l=List([1,2,3])
# l.clear() #此时没有权限,抛出异常

l.permission=True
print(l)
l.clear()
print(l)

#基于授权,获得insert方法
l.insert(0,-123)
print(l)

五 getattribute

回顾__getattr__

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]

f1=Foo(10)
print(f1.x)
f1.xxxxxx #不存在的属性访问,触发__getattr__

getattribute

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')

f1=Foo(10)
f1.x
f1.xxxxxx

二者同时出现

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]
    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')
        raise AttributeError('哈哈')

f1=Foo(10)
f1.x
f1.xxxxxx

#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

六 描述符(get,set,delete)

1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),set(),delete()中的一个,这也被称为描述符协议 get():调用一个属性时,触发 set():为一个属性赋值时,触发 delete():采用del删除属性时,触发

定义一个描述符

class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        pass
    def __delete__(self, instance):
        pass

2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)

引子:描述符类产生的实例进行属性操作并不会触发三个方法的执行

class Foo:
    def __get__(self, instance, owner):
        print('触发get')
    def __set__(self, instance, value):
        print('触发set')
    def __delete__(self, instance):
        print('触发delete')

#包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法
f1=Foo()
f1.name='egon'
f1.name
del f1.name
#疑问:何时,何地,会触发这三个方法的执行

描述符应用之何时?何地?

#描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')
    def __set__(self, instance, value):
        print('Str设置...')
    def __delete__(self, instance):
        print('Str删除...')

#描述符Int
class Int:
    def __get__(self, instance, owner):
        print('Int调用')
    def __set__(self, instance, value):
        print('Int设置...')
    def __delete__(self, instance):
        print('Int删除...')

class People:
    name=Str()
    age=Int()
    def __init__(self,name,age): #name被Str类代理,age被Int类代理,
        self.name=name
        self.age=age

#何地?:定义成另外一个类的类属性

#何时?:且看下列演示

p1=People('alex',18)

#描述符Str的使用
p1.name
p1.name='egon'
del p1.name

#描述符Int的使用
p1.age
p1.age=18
del p1.age

#我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__)

#补充
print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)

3 描述符分两种 一 数据描述符:至少实现了__get__()和__set__()

class Foo:
    def __set__(self, instance, value):
        print('set')
    def __get__(self, instance, owner):
        print('get')

二 非数据描述符:没有实现__set__()

class Foo:
    def __get__(self, instance, owner):
        print('get')

4 注意事项: 一 描述符本身应该定义成新式类,被代理的类也应该是新式类 二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中 三 要严格遵循该优先级,优先级由高到底分别是 1.类属性 2.数据描述符 3.实例属性 4.非数据描述符 5.找不到的属性触发__getattr__()

类属性>数据描述符

#描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')
    def __set__(self, instance, value):
        print('Str设置...')
    def __delete__(self, instance):
        print('Str删除...')

class People:
    name=Str()
    def __init__(self,name,age): #name被Str类代理,age被Int类代理,
        self.name=name
        self.age=age

#基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典

#那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错
People.name #恩,调用类属性name,本质就是在调用描述符Str,触发了__get__()

People.name='egon' #那赋值呢,我去,并没有触发__set__()
del People.name #赶紧试试del,我去,也没有触发__delete__()
#结论:描述符对类没有作用-------->傻逼到家的结论

'''
原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级
People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()

People.name='egon' #那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()
del People.name #同上
'''

数据描述符>实例属性

#描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')
    def __set__(self, instance, value):
        print('Str设置...')
    def __delete__(self, instance):
        print('Str删除...')

class People:
    name=Str()
    def __init__(self,name,age): #name被Str类代理,age被Int类代理,
        self.name=name
        self.age=age

p1=People('egon',18)

#如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
p1.name='egonnnnnn'
p1.name
print(p1.__dict__)#实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
del p1.name

实例属性>非数据描述符

class Foo:
    def func(self):
        print('我胡汉三又回来了')
f1=Foo()
f1.func() #调用类的方法,也可以说是调用非数据描述符
#函数是一个非数据描述符对象(一切皆对象么)
print(dir(Foo.func))
print(hasattr(Foo.func,'__set__'))
print(hasattr(Foo.func,'__get__'))
print(hasattr(Foo.func,'__delete__'))
#有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了
#笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么
#函数就是一个由非描述符类实例化得到的对象
#没错,字符串也一样

f1.func='这是实例属性啊'
print(f1.func)

del f1.func #删掉了非数据
f1.func()

再次验证:实例属性>非数据描述符

class Foo:
    def __set__(self, instance, value):
        print('set')
    def __get__(self, instance, owner):
        print('get')
class Room:
    name=Foo()
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

#name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级
#对实例的属性操作,触发的都是描述符的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房'

class Foo:
    def __get__(self, instance, owner):
        print('get')
class Room:
    name=Foo()
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

#name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级
#对实例的属性操作,触发的都是实例自己的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房'

非数据描述符>找不到

class Foo:
    def func(self):
        print('我胡汉三又回来了')

    def __getattr__(self, item):
        print('找不到了当然是来找我啦',item)
f1=Foo()

f1.xxxxxxxxxxx

5 描述符使用

众所周知,python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能

牛刀小试

class Str:
    def __init__(self,name):
        self.name=name
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

class People:
    name=Str('name')
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

p1=People('egon',18,3231.3)

#调用
print(p1.__dict__)
p1.name

#赋值
print(p1.__dict__)
p1.name='egonlin'
print(p1.__dict__)

#删除
print(p1.__dict__)
del p1.name
print(p1.__dict__)

拔刀相助

class Str:
    def __init__(self,name):
        self.name=name
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

class People:
    name=Str('name')
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

#疑问:如果我用类名去操作属性呢
People.name #报错,错误的根源在于类去操作属性时,会把None传给instance

#修订__get__方法
class Str:
    def __init__(self,name):
        self.name=name
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

class People:
    name=Str('name')
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary
print(People.name) #完美,解决

磨刀霍霍

class Str:
    def __init__(self,name,expected_type):
        self.name=name
        self.expected_type=expected_type
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        if not isinstance(value,self.expected_type): #如果不是期望的类型,则抛出异常
            raise TypeError('Expected %s' %str(self.expected_type))
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

class People:
    name=Str('name',str) #新增类型限制str
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

p1=People(123,18,3333.3)#传入的name因不是字符串类型而抛出异常

大刀阔斧

class Typed:
    def __init__(self,name,expected_type):
        self.name=name
        self.expected_type=expected_type
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        if not isinstance(value,self.expected_type):
            raise TypeError('Expected %s' %str(self.expected_type))
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

class People:
    name=Typed('name',str)
    age=Typed('name',int)
    salary=Typed('name',float)
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

p1=People(123,18,3333.3)
p1=People('egon','18',3333.3)
p1=People('egon',18,3333)

大刀阔斧之后我们已然能实现功能了,但是问题是,如果我们的类有很多属性,你仍然采用在定义一堆类属性的方式去实现,low,这时候我需要教你一招:独孤九剑

类的装饰器:无参

def decorate(cls):
    print('类的装饰器开始运行啦------>')
    return cls

@decorate #无参:People=decorate(People)
class People:
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

p1=People('egon',18,3333.3)

类的装饰器:有参

def typeassert(**kwargs):
    def decorate(cls):
        print('类的装饰器开始运行啦------>',kwargs)
        return cls
    return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

p1=People('egon',18,3333.3)

终极大招

刀光剑影

class Typed:
    def __init__(self,name,expected_type):
        self.name=name
        self.expected_type=expected_type
    def __get__(self, instance, owner):
        print('get--->',instance,owner)
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        print('set--->',instance,value)
        if not isinstance(value,self.expected_type):
            raise TypeError('Expected %s' %str(self.expected_type))
        instance.__dict__[self.name]=value
    def __delete__(self, instance):
        print('delete--->',instance)
        instance.__dict__.pop(self.name)

def typeassert(**kwargs):
    def decorate(cls):
        print('类的装饰器开始运行啦------>',kwargs)
        for name,expected_type in kwargs.items():
            setattr(cls,name,Typed(name,expected_type))
        return cls
    return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary

print(People.__dict__)
p1=People('egon',18,3333.3)

6 描述符总结

描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性

描述父是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件.

7 利用描述符原理完成一个自定制@property,实现延迟计算(本质就是把一个函数属性利用装饰器原理做成一个描述符:类的属性字典中函数名为key,value为描述符类产生的对象)

@property回顾

class Room:
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

    @property
    def area(self):
        return self.width * self.length

r1=Room('alex',1,1)
print(r1.area)

自己做一个@property

class Lazyproperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, owner):
        print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
        if instance is None:
            return self
        return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情

class Room:
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

    @Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
    def area(self):
        return self.width * self.length

r1=Room('alex',1,1)
print(r1.area)

实现延迟计算功能

class Lazyproperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, owner):
        print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
        if instance is None:
            return self
        else:
            print('--->')
            value=self.func(instance)
            setattr(instance,self.func.__name__,value) #计算一次就缓存到实例的属性字典中
            return value

class Room:
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

    @Lazyproperty #area=Lazyproperty(area) 相当于'定义了一个类属性,即描述符'
    def area(self):
        return self.width * self.length

r1=Room('alex',1,1)
print(r1.area) #先从自己的属性字典找,没有再去类的中找,然后出发了area的__get__方法
print(r1.area) #先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算

一个小的改动,延迟计算的美梦就破碎了

#缓存不起来了

class Lazyproperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, owner):
        print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
        if instance is None:
            return self
        else:
            value=self.func(instance)
            instance.__dict__[self.func.__name__]=value
            return value
        # return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情
    def __set__(self, instance, value):
        print('hahahahahah')

class Room:
    def __init__(self,name,width,length):
        self.name=name
        self.width=width
        self.length=length

    @Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
    def area(self):
        return self.width * self.length

print(Room.__dict__)
r1=Room('alex',1,1)
print(r1.area)
print(r1.area)
print(r1.area)
print(r1.area) #缓存功能失效,每次都去找描述符了,为何,因为描述符实现了set方法,它由非数据描述符变成了数据描述符,数据描述符比实例属性有更高的优先级,因而所有的属性操作都去找描述符了

8 利用描述符原理完成一个自定制@classmethod

自己做一个@classmethod

class ClassMethod:
    def __init__(self,func):
        self.func=func

    def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
        def feedback():
            print('在这里可以加功能啊...')
            return self.func(owner)
        return feedback

class People:
    name='linhaifeng'
    @ClassMethod # say_hi=ClassMethod(say_hi)
    def say_hi(cls):
        print('你好啊,帅哥 %s' %cls.name)

People.say_hi()

p1=People()
p1.say_hi()
#疑问,类方法如果有参数呢,好说,好说

class ClassMethod:
    def __init__(self,func):
        self.func=func

    def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
        def feedback(*args,**kwargs):
            print('在这里可以加功能啊...')
            return self.func(owner,*args,**kwargs)
        return feedback

class People:
    name='linhaifeng'
    @ClassMethod # say_hi=ClassMethod(say_hi)
    def say_hi(cls,msg):
        print('你好啊,帅哥 %s %s' %(cls.name,msg))

People.say_hi('你是那偷心的贼')

p1=People()
p1.say_hi('你是那偷心的贼')

9 利用描述符原理完成一个自定制的@staticmethod

自己做一个@staticmethod

class StaticMethod:
    def __init__(self,func):
        self.func=func

    def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
        def feedback(*args,**kwargs):
            print('在这里可以加功能啊...')
            return self.func(*args,**kwargs)
        return feedback

class People:
    @StaticMethod# say_hi=StaticMethod(say_hi)
    def say_hi(x,y,z):
        print('------>',x,y,z)

People.say_hi(1,2,3)

p1=People()
p1.say_hi(4,5,6)

六 再看property

一个静态属性property本质就是实现了get,set,delete三种方法

用法一

class Foo:
    @property
    def AAA(self):
        print('get的时候运行我啊')

    @AAA.setter
    def AAA(self,value):
        print('set的时候运行我啊')

    @AAA.deleter
    def AAA(self):
        print('delete的时候运行我啊')

#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

用法二

class Foo:
    def get_AAA(self):
        print('get的时候运行我啊')

    def set_AAA(self,value):
        print('set的时候运行我啊')

    def delete_AAA(self):
        print('delete的时候运行我啊')
    AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应

f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

怎么用?

案例一

class Goods:

    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price

    @price.setter
    def price(self, value):
        self.original_price = value

    @price.deleter
    def price(self):
        del self.original_price

obj = Goods()
obj.price         # 获取商品价格
obj.price = 200   # 修改商品原价
print(obj.price)
del obj.price     # 删除商品原价

案例二

#实现类型检测功能

#第一关:
class People:
    def __init__(self,name):
        self.name=name

    @property
    def name(self):
        return self.name

# p1=People('alex') #property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常

#第二关:修订版

class People:
    def __init__(self,name):
        self.name=name #实例化就触发property

    @property
    def name(self):
        # return self.name #无限递归
        print('get------>')
        return self.DouNiWan

    @name.setter
    def name(self,value):
        print('set------>')
        self.DouNiWan=value

    @name.deleter
    def name(self):
        print('delete------>')
        del self.DouNiWan

p1=People('alex') #self.name实际是存放到self.DouNiWan里
print(p1.name)
print(p1.name)
print(p1.name)
print(p1.__dict__)

p1.name='egon'
print(p1.__dict__)

del p1.name
print(p1.__dict__)

#第三关:加上类型检查
class People:
    def __init__(self,name):
        self.name=name #实例化就触发property

    @property
    def name(self):
        # return self.name #无限递归
        print('get------>')
        return self.DouNiWan

    @name.setter
    def name(self,value):
        print('set------>')
        if not isinstance(value,str):
            raise TypeError('必须是字符串类型')
        self.DouNiWan=value

    @name.deleter
    def name(self):
        print('delete------>')
        del self.DouNiWan

p1=People('alex') #self.name实际是存放到self.DouNiWan里
p1.name=1
Python中的函数、闭包、装饰器、lambda表达式、生成器和递归 首先是最简单的函数定义问题(后面附有代码的执行结果) 阅读详情

相关推荐

小甲鱼《零基础入门学习Python》学习笔记

根据老师的建议,现在将第二次复习小甲鱼的《零基础入门学习Python》而做的学习笔记,上传到网上,方便今后复习和保存,因为是手写的,所以做了扫描锐化处理,方便阅读。 ...

baidu_32335419的博客 1万+

LeetCode题解(1819):序列中不同最大公约数的数目(Python)

题目:原题链接(困难) 标签:数学 解法 时间复杂度 空间复杂度 执行用时 Ans 1 (Python) O(N+ClogC)O(N+ClogC)O(N+ClogC) O(C)O(C)O(C) 3052ms (82.32%) Ans 2 (Python) Ans 3 (Python) 解法一: import math class Solution: _MAXIMUM = 2 * (10 ** 5) def countDifferentSubseq

长行 4561

Python: list列表的11个内置方法

前言 在实际开发中,经常需要将一组(不只一个)数据存储起来,以便后边的代码使用。在VBA中有使用数组,可以把多个数据存储 到一起,通过数组下标可以访问数组中的每个元素。Python 中没有数组,但是加入了更加强大的列表(list)。下面就对列表的内 置方法进行介绍。 通过dir(list)可以查看列表的属性和内置方法。 print(dir(list)) Python学习交流Q群:906715085### ['__add__', '__class__', '__contains__', '__delat

xff123456_的博客 2085

Python三引号

Python三引号。

CJ101819的博客 7319

〖Python零基础入门篇㊶〗- Python中内置异常类型

上一章节我们学习了如何捕获异常,并且针对 通用异常 与 具体异常 的捕获进行了详细的讲解。今天给大家讲解一下 Python 中常用的内置异常类型的捕获,希望通过对它们的了解,可以帮助我们更好的使用并捕获异常。 该章节只有一个目的,那就是了解常用的异常类型。

易编橙 · 终身成长社群,相遇已是上上签! 4万+

【Python技术学习】- Python内置界面开发框架 Tkinter入门篇

上期讲过,python 其实有三大流行 GUI 开发框架,包括 PyQt、wxPython 和 Tkinter。wxPython 也在上期文章介绍过,今天给大伙带来 Tkinter 的入门介绍!Tkinter 是 python 标准库内嵌自带的界面开发框架,算得上是皇亲国戚了。如此火热的 python ,又怎能不了解一下它自带的界面开发框架呢?Tkinter 有很多强大的地方,比如跨平台特性。同一套代码可以轻松运行在 Windows, macOS 和 Linux 系统环境下。

xiaoli8748的专栏 1415

python2018.9.19内容

操作系统 操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。 #1. 打开文件,得到文件句柄并赋值给一个变量 f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r #2. 通过句柄对文件进行操作 data=f.r...

a482299的博客 6530

用Python玩转共现分析:从NLTK到热力图可视化(附完整代码)

本文详细介绍了如何使用Python进行文本共现分析,从NLTK基础文本处理到构建共现矩阵,并实现热力图可视化。通过完整的代码示例,帮助数据分析师和开发者掌握这一揭示词语间关联网络的实用NLP技术,快速从文本中提取语义关系和主题结构。

weixin_29313817的博客 350

Python内置方法干货总结

在如今AI和大数据加速发展的时代,代码质量与开发速度变得前所未有的重要。越来越多的企业在招聘Python开发时,特别看重应聘者对基础能力的掌握,比如内置方法的熟练运用。这不仅是技术实力的体现,更是对工程思维的考验。Python内置方法是开发者手中的“魔法棒”,从len()到zip(),它们简化了复杂任务,让代码更简洁、优雅。掌握这些方法,不仅提升开发效率,还让你更贴近Python的哲学——用最少代码实现最大价值。无论是数据分析、Web开发还是自动化脚本,这些内置方法都是你的得力助手。

朱雀随云记的博客 1322

将点云坐标转换成世界坐标的demo

将点云坐标转换成世界坐标的demo

howard789的博客 2206

AI驱动的数据完整性:ECC到S/4HANA迁移

在SAP ECC到S/4HANA的迁移过程中,数据完整性验证是最复杂且关键的挑战之一。本文介绍了一个全面的AI驱动的端到端数据完整性框架,用于对账事务数据并验证数百万条主数据记录和事务记录的完整性。该框架结合了模式映射、自然语言提示到SQL生成、基于LLM的解决方案、大规模数据对账的数据完整性工具、基于云的测试数据管理以及实时Power BI仪表板,为开发者提供了一个可重复、可扩展的工作流程,确保ERP迁移过程中的数据质量。

简简单单Onlinezuozuo 1173

Python 进阶学习笔记之一:内置常用类型及方法

进阶学习 Python 内置常用功能函数、类以及模块

zombres的博客 566

openEuler 欧拉 安装Oracle19c数据库RPM包安装

欧拉系统安装部署oracle 19c rpm方式

陈苏漾的IT生涯 6893

Python入门学习笔记:Python函数

使用def 语句定义一个函数a语法# 函数体# 进行一些操作return result # 可选的返回值说明用于声明一个函数,告诉 Python 这是一个函数的定义。函数名,一个有效的标识符,规则和变量名一致。形参,可以是0 ~ n 个,参数之间用逗号分隔。定义函数执行的具体操作。指定函数的返回值,没有则返回None。return之后的代码不会执行。示例# 定义一个 lambda 函数,接收两个参数 a 和 b,返回它们的和​print(add(3, 5)) # 输出: 8。

PQI_JiXian的博客 1775

Arm A-profile架构RAS系统设计:可靠性、可用性与可服务性解析

在计算机体系结构中,可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)是构建高可信系统的核心要素。RAS系统通过硬件错误检测、隔离和恢复机制,确保系统持续稳定运行。其技术原理包括ECC内存纠错、冗余执行单元和错误传播阻断等关键技术,可显著降低数据中心等关键业务场景的故障率。现代芯片设计中,Arm A-profile架构提供标准化的RAS框架,涵盖从内存子系统到计算单元的全方位错误管理。通过分层防御策略和统一错误记录格式,实现硬件错误可追溯、可修复。

weixin_30920853的博客 357

UE5 StateTree实战:用分层状态机重构你的AI行为逻辑(附蓝图配置避坑点)

本文详细介绍了UE5中StateTree分层状态机的实战应用,帮助开发者重构AI行为逻辑。通过核心概念解析、迁移策略、高级技巧和避坑指南,展示了StateTree在灵活性、可维护性和并行处理方面的优势,特别适合复杂AI行为的开发与优化。

weixin_42558257的博客 249

Python 笔记 | 常用的内置类、内置方法

python常用的类、常用的方法

JUST FOR FUN, CALM DOWN 964

Ubuntu22.04如何安装cuDNN8.9.7

本文详细介绍了在Ubuntu 22.04系统上为CUDA 12.2安装适配cuDNN 8.9.7的完整流程,特别针对RTX A6000显卡。主要内容包括:1)选择与CUDA 12.2兼容的cuDNN版本;2)使用deb包方式的安装步骤(添加仓库、导入密钥、安装组件);3)通过MNIST示例验证安装;4)版本锁定、卸载旧版等补充说明;5)性能测试方法。文中强调了版本匹配的重要性,并提供了多卡配置建议,为搭建深度学习开发环境提供完整指导。

2501_93651177的博客 1845

python之字符串类型内置方法

python之字符串类型内置方法 文章目录python之字符串类型内置方法引入一.定义方式二.数据类型转换三.常用操作 + 内置方法优先掌握的操作(***\******)1.按照索引取值(正向取+反向取)2、切片:索引的拓展应用3、长度`len`:统计的是字符个数4、成员运算`in` 和 `not in`5、移除空白 `strip`6、切分`split`7、循环需要掌握的操作()1.`strip,lstrip,rstrip`: 不同方向移除指定符号2、`lower, upper`: 小写,大写3、`star

淘小欣的博客 2057

OpenClaw进阶实战(二十一):工作流6:跨平台舆情监控与自动响应

摘要: 本文介绍基于OpenClaw构建自动化舆情监控系统,实现多平台数据采集、AI情感分析与智能预警。系统架构包含数据采集(微博/小红书/抖音)、消息队列、情感分析(SnowNLP/大模型API)、分级预警和自动响应模块。通过技能化开发(如微博API采集、小红书模拟登录)实现7×24小时监控,结合情感强度与传播速度分级处理负面舆情,形成"采集-分析-预警-处置"闭环,适用于企业私有化部署。

PeterPan的博客 299

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Python:深入探索内置方法

Python是一种高级编程语言,以其简洁和强大而闻名。Python3作为其最新的主要版本,提供了许多内置方法,这些方法是提高编程效率和简化代码开发的强大工具。在这篇文章中,我们将详细介绍Python3的一些关键内置方法,并展示它们在实际编程中的应用。

十年运维开发经验的王义杰在此分享自己的知识和经验 887

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

在 Python 中,内置类型的行为是通过一组特殊的“魔法方法”来实现的,这些魔法方法以双下划线开头和结尾,比如 init 和 str,你可以通过重写这些魔法方法来定制或扩展内置类型的行为。

weixin_44719294的博客 2200

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【Python】内置 方法、语法 合集

ord(ch)chr(d)hex(d)int(ch)list(str)str.join(l)str.split(ch)l.index(v)l.reverse()l.remove(v)l.insert(i, v)l.count(v)l.pop(i)l.append(v)l.extend()l.clear l.sort()min()max()set()enumerate(l)str.isupper()str.islower()str.encode()str.decode()str.stripstr.format

m0_46296905的博客 393

序列的力量——Python 内置方法的魔法解密

简单来说,内置方法(Built-in Methods)是 Python 自带的、可以直接使用的函数或功能。这些方法无需导入任何库,直接开箱即用,就能快速完成数据处理。💡比喻理解眼睛是人类自带的器官,可以观察世界;内置方法是 Python 自带的“眼睛”,让程序员能迅速理解并操作数据。很多初学者容易陷入“背方法”的陷阱,其实没必要。你只需要知道 Python 提供了哪些“能力”,用到时再查笔记就行。正如老师说的那句经典话:“学完这堂课,对这些方法有个了解就行,用的时候再回来看。💡。

qq_21106275的博客 1045

python之列表类型内置方法

python之列表类型内置方法 文章目录python之列表类型内置方法引入一.定义方式二.类型转换三.常用操作 + 内置方法优先掌握的操作(***\******)1、按索引取值(正+反向)+ 可以取值也可以改值2、切片,顾头不顾尾 + 步长3、长度4、成员运算 in 和 not in5、追加 .append()6、插入 .insert()7、删除 del, remove, pop7、循环取值需要掌握的操作()1.统计字符的个数 : .count()2.扩展,追加多个值 : .extend()3.清空列表 :

淘小欣的博客 1607

Python基础教程:字典类型内置方法

造字典方式三info = [[‘name’,‘lwx’],[‘age’,18],[‘gender’,‘male’]]res = dict(info)print(res){‘name’: ‘lwx’, ‘age’: 18, ‘gender’: ‘male’}造字典方式四快速初始化一个字典keys = [‘name’,‘age’,‘gender’]d={}.fromkeys(keys,22)print(d)#{‘name’: None, ‘age’: None, ‘gender’: None}常用操作和内置方法

2401_83817122的博客 1157
上一篇: python入门开发学习笔记之绑定方法与非绑定方法
下一篇: python入门学习笔记之内置方法(二)
程序员_大白
博客等级 码龄5年 1万+粉丝 4001原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值