26.Python编程:获取对象信息

# 创建一个猫类对象c
c = Cat()
c.eat()

思考:当我们拿到一个对象的引用时,我们能通过该引用获取该对象的哪些信息呢?例如:创建了一个猫类对象c,我们能根据c,获取到哪些数据信息呢?

再思考:一个对象哪些数据信息是我们开发时所关心的呢?正如你所想到的:对象所属的类型、对象的属性、方法等信息。

本文就来通过对象的引用获取该对象类型、所有的属性和方法。

接下来,我们用Python中自带的函数,来获取以上重要信息。现在我们设计object_info.py模块:包含了Animal类、Cat类、Dog类,代码如下。

# 定义一个动物类Animal
class Animal(object):
    legs = ''  # 腿的数量
    color = ''  # 毛色

    def eat(self):
        print("Animal吃东西")

    def sleep(self):
        print("Animal睡觉")

    def walk(self):
        print("Animal走路")


# 定义一个猫类Cat,继承自动物类Animal
class Cat(Animal):

    def eat(self):
        print("小猫吃鱼")

    def sleep(self):
        print("小猫呼呼睡觉")

    def walk(self):
        print("小猫走猫步")


# 定义一个狗类Dog,继承自动物类Animal
class Dog(Animal):

    def eat(self):
        print("小狗啃骨头")

    def sleep(self):
        print("小狗高度警惕的睡觉")

    def walk(self):
        print("小狗飞奔")

获取类型type(obj)

class type(obj)官方解释:

With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.

意思大概是说:type函数传入一个参数时,返回结果是该对象的类型。返回值是type对象,和调用该对象的__class__方法返回值一样。

写出测试代码如下:

# 创建猫类对象c1
c1 = Cat()

# type(obj)
print("type(c1)", type(c1))
print("c1.__class__", c1.__class__)

运行结果:

type(c1): <class '__main__.Cat'>
c1.__class__: <class '__main__.Cat'>

正如官方解释的一样:当type函数传入一个参数时,返回结果是该对象的类型,返回值和调用该对象的__class__方法返回值一样,是一type类型对象。

看到打印结果,这里c1、c2的类型打印结果是:__main__.Cat,为什么多了一部分__main__?前面讲过__main__则是表示我直接运行的当前模块,也就是本例子中object_info.py模块,而不是该模块被其他模块唤起的。

我们再设计另一个模块,my_test.py。文件结构如下:

文件结构示意图

from object_infos.object_info import Cat

print("--object_info模块被唤起的---")

这次我们运行my_test.py,因为该模块导入了object_info.py模块中的Cat类,所以object_info.py是被动唤起调用的。

运行结果:

type(c1): <class 'object_infos.object_info.Cat'>
c1.__class__: <class 'object_infos.object_info.Cat'>
--object_info模块被唤起的---

看到打印结果,这里c1、c2的类型打印结果不再含有:__main__,而是打印的全类名:object_infos.object_info.Cat。即:object_infos包下的object_info模块中的Cat类。

补充 isinstance(obj, type)

isinstance(obj, type) 函数专门用于判断一个对象是否某个类型。官方解释:

The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.

意思大概是:当试图判断一个对象是否某个类型时,推荐使用 Python内置的函数isinstance(obj, type),因为该函数会把具有继承关系的类考虑在内。

这怎么理解呢?
object_info.py模块中添加如下代码:

# 创建狗类对象d
d = Dog()
print("isinstance(d, Dog):", isinstance(d, Dog))
print("isinstance(d, Animal):", isinstance(d, Animal))

运行结果:

isinstance(d, Dog): True
isinstance(d, Animal): True

可以看到:狗对象d是狗类实例;狗对象d也是动物类实例,都是True。也就是我们通常所理解的:狗是狗(True),狗是动物(True)。因为Dog类继承自Aniaml类,所以Python内置的函数isinstance(obj, type),会把具有继承关系的类考虑在内。

dir()函数:获取属性和方法

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法。dir()函数官方解释如下:

Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.

意思大概是:dir()函数,如果调用时无参调用,则返回当前本地范围中的名称列表。如果调用时传入一个对象参数,则尝试返回该对象的所有的有效属性列表。

也就是传一个对象参数则可返回该对象的所有属性和方法。由于dir()无参时涉及到上下文中,为了更好地看出无参和有餐的dir()函数调用区别,这里把整个模块objcet_info.py贴出来:

# 定义一个动物类Animal
class Animal(object):
    legs = ''  # 腿的数量
    color = ''  # 毛色

    def eat(self):
        print("Animal吃东西")

    def sleep(self):
        print("Animal睡觉")

    def walk(self):
        print("Animal走路")


# 定义一个猫类Cat,继承自动物类Animal
class Cat(Animal):

    def eat(self):
        print("小猫吃鱼")

    def sleep(self):
        print("小猫呼呼睡觉")

    def walk(self):
        print("小猫走猫步")


# 定义一个狗类Dog,继承自动物类Animal
class Dog(Animal):

    def eat(self):
        print("小狗啃骨头")

    def sleep(self):
        print("小狗高度警惕的睡觉")

    def walk(self):
        print("小狗飞奔")


# 创建狗类对象d
d = Dog()
print("isinstance(d, Dog):", isinstance(d, Dog))
print("isinstance(d, Animal):", isinstance(d, Animal))

print("dir()无参调用:", dir())
print("dir(d)传入参数时:", dir(d))

运行结果:

dir()无参调用: ['Animal', 'Cat', 'Dog', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'd']
dir(d)传入参数时: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'eat', 'legs', 'sleep', 'walk']

使用dir()函数,如果调用时无参调用,则返回当前本地范围中的名称列表,如:'Animal', 'Cat', 'Dog','d'等数据。
如果调用时传入一个对象参数,则尝试返回该对象的所有的有效属性列表。如上运行结果所示。

补充 class type(name, bases, dict)

前面在将type()函数时,官方解释中强调了一个参数的,是因为还有一个同名函数,但需要传入三个参数的,可以动态创建新的class对象,也就是新类型,如:通过该函数动态创建Fox类。 class type(name, bases, dict)的官方解释如下:

With three arguments, return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the name attribute; the bases tuple itemizes the base classes and becomes the bases attribute; and the dict dictionary is the namespace containing definitions for class body and is copied to a standard dictionary to become the dict attribute. For example, the following two statements create identical type objects。

要创建一个class对象,type()函数依次传入3个参数:
1.新class的名称;
2.所要继承的父类的集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
3.新class中的方法名称与函数可通过字典键值对一一绑定。例如:此参数传入:dict(my_eat=eat)这里我们把函数eat绑定到方法名my_eat上。

通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。

看到这里,你会发现这与Java中的反射机制类似的:运行时动态创建的对象、绑定属性、方法等。接下在学习元类时会专门学习这一块内容。

小结

本文通过对象的引用获取该对象类型、所有的属性和方法。

type()函数传入一个参数时,返回结果是该对象的类型。返回值是type对象,和调用该对象的__class__方法返回值一样。

isinstance(obj, type) 函数专门用于判断一个对象是否某个类型。

dir()函数,如果调用时无参调用,则返回当前本地范围中的名称列表。如果调用时传入一个对象参数,则尝试返回该对象的所有的有效属性列表。

class type(name, bases, dict)可以创建出新的类型。类似Java中的反射机制。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容