关于运维:Python8对象与类中

3次阅读

共计 4213 个字符,预计需要花费 11 分钟才能阅读完成。

引言

这篇文章介绍 Python 如何将函数与数据整合成类,并通过一个对象名称来拜访它们。

文章目录

0×5. 获取对象信息
0×6. 实例属性与类属性
0×7. 属性和办法的动静绑定
0×8. 如何将类办法封装成属性

0×5. 获取对象信息

除了应用 isinstance 来匹配对象类型外,还能应用 type 来获取这些对象的类型,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
#types 模块中定义的常量可用于判断函数类型
import types

#输入对象的类型
print(type("www.qingsword.com"))
#判断对象是否为字符串类型
print(type("qingsword.com")==str)
#程序输入
<class 'str'>
TRUE

#如果对象是一个函数,就须要借助 types 模块中定义的常量来判断了
#--------
def fx():
    return 0

#判断 fx 是否为函数类型
print(type(fx)==types.FunctionType)

#判断是否为 lambda 类型
print(type(lambda :0)==types.LambdaType)

#判断 len 是否为内置的函数类型
print(type(len)==types.BuiltinFunctionType)

#判断表达式是否为列表生成器类型
print(type((x for x in range(10)))==types.GeneratorType)

#程序输入都为 True

#isinstance 同样可能实现这些操作,例如将判断 fx 函数的语句改成上面这样,返回值同样是 True
print(isinstance(fx,types.FunctionType))

除了下面的两种对象类型判断外,配合 getattr()、setattr()以及 hasattr(),咱们能够间接操作一个对象的状态,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
class Ob_A(object):
    #---------
    def __init__(self,x=0):
        if type(x)==int:
            self.a=x
        else:
            raise TypeError("传入参数类型 (%s) 谬误, 正确的参数类型 int"%type(x))
    #---------
    def sq(self):
        return self.a*self.a

oba=Ob_A(12)

#判断 oba 对象中是否有属性(或办法)a,返回 True
print(hasattr(oba,"a"))

#获取属性(或办法)a,本例中 a 是一个属性值 12,所以被 print 间接打印了进去
print(getattr(oba,"a"))

#是否有属性(或办法)b,返回 False
print(hasattr(oba,"b"))

#给对象设置一个属性 b,值为 13
setattr(oba,"b",13)

#因为曾经给对象增加了属性 b,再次判断,返回 True,并且打印出 b 的值 13
print(hasattr(oba,"b"))
print(getattr(oba,"b"))

#判断 oba 对象中是否存在 sq 属性(或办法)
print(hasattr(oba,"sq"))

#应用 sq 对象指向 oba 对象的 sq 办法
sq=getattr(oba,"sq")

#从 type 能够看到 sq 是一个办法类型
print(type(sq))

#执行 sq 办法,返回 144
print(sq())

#程序输入
TRUE
12
FALSE
TRUE
13
TRUE
<class 'method'>
144

这三个函数可用于探测对象中的信息,只有在不晓得对象信息的时候,才会应用这三个函数,如果曾经明确晓得了一个对象中蕴含了哪些属性和办法,请间接调用他们。

0×6. 实例属性与类属性

python 是动静语言,在实例化后,还能给实例增加新的属性,但最好不要与类中的属性同名,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
#Ob_A 类中定义了一个类属性 x,并且配置了其值为 2
class Ob_A(object):
    x=2

#实例化 Ob_A 类
oba=Ob_A()

#给 oba 实例创立一个新属性 x,因为和 Ob_A 类中的属性同名,所以会笼罩原有属性值
oba.x=1

#打印出 1
print(oba.x)

#类中的属性放弃不变,打印出 2
print(Ob_A.x)

#此时如果手动删除 oba 实例的 x 对象,再次打印 oba 实例的 x 对象,就会打印出原类中绑定的属性 x 值,打印出 2
del oba.x
print(oba.x)

#程序输入
1
2
2

类在实例化后,如果须要给实例新增属性,倡议属性名不要应用与原类中曾经存在的属性同名,因为雷同名称的实例属性将屏蔽掉类属性。

0×7. 属性和办法的动静绑定

Python 属于高级动静语言,与动态语言不同,当咱们实例化一个类对象后,能够动静的给这个类实例绑定属性或办法,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
from types import MethodType

#定义一个类,仅蕴含一个 age 属性
class Ob_A(object):
    def __init__(self,age=0):
        self.age=age

#实例化 Ob_A 类
a=Ob_A(23)
#给 Ob_A 类的实例 a 新增一个 name 属性
a.name="qingsword"

#定义一个内部办法,稍后将它绑定到 a 实例
def get_sex(self):
    return "male"

#应用 types 模块中的 MethodType 办法,将 get_sex 这个内部办法绑定到 a 实例的 getsex 变量上
a.getsex=MethodType(get_sex,a)

#执行 a 实例的 getsex()就相当于执行了 get_sex()
print(a.getsex())

#程序输入
male

#getsex 名称仅限于 a 实例调用,如果此时再实例化一个 Ob_A 类,除非再次应用 MethodType 绑定一个新的 get_sex 办法,否则这个新的类实例是不能应用 get_sex 这个内部办法的

从下面这个实例能够看出,Python 不会限度一个对象实例绑定多少内部属性和办法,但如果要限度他们,能够在类中应用__slots__属性,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
from types import MethodType
########
class Ob_A(object):
    def __init__(self,age=0):
        self.age=age
    #定义了 __slots__属性后,Ob_A 本身和所有实例,都只能应用这个元组中所蕴含的元素作为属性或办法名称
    __slots__=("name","age","get_sex")
########
#但__slots__属性对继承它的子类有效,除非这个子类中也蕴含一个__slots__属性,那么这个子类能够定义的属性或办法名就是本人的__slots__元组中蕴含的元素加上父类__slots__元组中蕴含的元素的汇合
class Ob_B(Ob_A):
    x=0
########
def get_sex(self):
    return "male"
a=Ob_A(23)
a.name="qingsword"
a.get_sex=MethodType(get_sex,a)
print(a.get_sex())

#Ob_B 类尽管继承 Ob_A,但它没有蕴含__slots__属性,所以实例 b 能够增加任何属性或办法名,本例增加了一个 web 属性,指向了本站网址这段字符串地址
b=Ob_B()
b.web="www.qingsword.com"
print(b.web)

0×8. 如何将类办法封装成属性

这一部分将应用 python 内置的 @property 装璜器,将类中的办法转换成属性,在内部看来,这个办法就像一个一般属性那样应用,请看上面的实例:

#!/usr/bin/env python
#coding=utf-8
from datetime import datetime
########
class Ob_A(object):
    def __init__(self,birth=2016):
        """初始化配置出身年份"""
        self.__birth=birth
    #应用 @property 装璜器将 birth 办法转换成属性
    @property
    def birth(self):
        """获取出身年份"""
        return self.__birth
    #应用 @办法名.setter 将这个办法设置成可写属性(一个办法名称必须先应用过 property 装璜器,能力应用 setter)
    @birth.setter
    def birth(self,birth):
        """设置出身年份"""
        self.__birth=birth
    #仅有一个 @property 没有 setter 的办法,相当于一个只读属性
    @property
    def age(self):
        """返回年龄"""
        y=datetime.now()
        return y.year-self.__birth

x=Ob_A(2008)
print(x.birth)
#能够像设置属性值那样复制(如果是办法语法应该是 x.birth(2000))x.birth=2000
print(x.birth)
print(x.age)

#程序输入
2008
2000
16

尽管下面的实例中,并没有对年龄做进一步的检测(比方年龄范畴,输出类型等),但也不难看出,将函数封装成属性的款式能够让调用者写出更直观代码(比方 x.birth=2000,而不是 x.birth(2000)),而对封装者而言,能够在函数中去做各种条件判断来保障逻辑的正当。

正文完
 0