一、判断对象是否属于类、判断类是否派生自某个类

  1. class Zero:
  2. pass
  3. class One(Zero):
  4. pass
  5. class Two(One, Zero):
  6. pass
  7. # 判断对象是否完全是某个类
  8. print(type(Two()) == Two)#true
  9. print(type(Two()) == Zero)#false
  10. # 判断对象是否属于某个类
  11. print(isinstance(Two(), Zero))#true
  12. # 判断某个类是否是另一个类的子类
  13. print(Zero in Two.__bases__)#true
  14. print(issubclass(Two,Zero))

二、关于元类

在Python中,类型分为三个层次:元类、类、对象。

类是元类的实例化,对象是类的实例化。

在Python中,元类、类、对象三种东西相当于结点,它们之间的有向边表示继承关系。整个类型系统构成一个有向无环图。这个有向无环图分为三层,一个对象可以继承多个类。

metaclass的作用就是创建类

举一个小例子

  1. class BaseMetaClass(type):
  2. def __new__(cls, *args, **kwargs):
  3. kind = type.__new__(cls, *args, **kwargs)
  4. print(kind)
  5. return kind
  6. class Base(metaclass=BaseMetaClass):
  7. pass
  8. class One(Base):
  9. pass
  10. class Two(Base):
  11. pass

输出为

  1. <class '__main__.Base'>
  2. <class '__main__.One'>
  3. <class '__main__.Two'>

在此例中,只进行了类的声明,没有进行类的实例化。在进行类的声明过程中,会调用metaclass的new方法,new方法的返回值就是一个具体的类型。类型是特殊的对象。

Python中,内置函数type起的作用非常关键,它具有两个作用

  • type(obj)查看obj的类型,type(cls)查看cls的元类
  • type(className,*arg,*karg)构造函数产生新的类

在上述代码的基础上加几句话

  1. class Three:
  2. pass
  3. print(type(One))#<class '__main__.BaseMetaClass'>
  4. print(type(Three))#<class 'type'>
  5. print(type(type))#<class 'type'>

三、一切皆type

在Java中,一切皆是Object

在Python中,一切皆是type

  1. def f():
  2. pass
  3. ff = lambda: 0
  4. x = []
  5. for i in (list, dict, type, f, ff, x):
  6. while type(i) != i:
  7. print(i, end=' ')
  8. i = type(i)
  9. print(i)

输出为

  1. <class 'list'> <class 'type'>
  2. <class 'dict'> <class 'type'>
  3. <class 'type'>
  4. <function f at 0x000000CEE01B7F28> <class 'function'> <class 'type'>
  5. <function <lambda> at 0x000000CEE07E5A60> <class 'function'> <class 'type'>
  6. [] <class 'list'> <class 'type'>

四、函数中可以定义类,类中可以定义函数

函数是function类型,function是type类型

  1. >>> def choose_class(name):
  2. if name == 'foo':
  3. class Foo(object):
  4. pass
  5. return Foo # 返回的是类,不是类的实例
  6. else:
  7. class Bar(object):
  8. pass
  9. return Bar

  10. >>> MyClass = choose_class('foo')
  11. >>> print MyClass # 函数返回的是类,不是类的实例
  12. <class '__main__'.Foo>
  13. >>> print MyClass() # 你可以通过这个类创建类实例,也就是对象
  14. <__main__.Foo object at 0x89c6d4c>

五、使用type定义类型

type(类型名称,基类列表,属性字典)

  1. A = type("A", (), {
  2. 'name': 'weidiao',
  3. 'age': 23,
  4. '__str__': lambda self: '{},{}'.format(self.name, self.age)
  5. })
  6. x = A()
  7. print(x)#输出为weidiao,23

六、__class__属性

__class__属性时是每一种类型必然包含的属性,该属性的取值相当于x.__class==type(x)

七、不要忘记python是一门脚本语言

下面定义了一个类A,它有name和age两个属性,但是我可以随意给这个对象添加属性。

  1. A = type("A", (), {
  2. 'name': 'weidiao',
  3. 'age': 23,
  4. '__str__': lambda self: '{},{},{}'.format(self.name, self.age,self.baga)#如果没有baga属性,此处会报错
  5. })
  6. x = A()
  7. x.baga='3'
  8. print(x)

八、调用父类构造函数的两种方法

在Java和C++中,子类的构造函数都会自动调用父类的构造函数。

在Python中,子类是不会自动调用父类的构造函数的,因为在Python中没有构造函数,而只有初始化函数!而初始化函数只相当于普普通通的函数,所以,这就需要我们手动来调用父类的构造函数。

首先来看,如果不调用父类构造函数会出现什么情况

  1. class A:
  2. def __init__(self, name, age):
  3. self.name = name
  4. self.age = age
  5. def __str__(self):
  6. return self.name + str(self.age)
  7. class B(A):
  8. def __init__(self):
  9. pass
  10. b = B()
  11. print(b)

在此例中,B类没有调用A类的初始化函数,所以B类就缺少了name和age属性,B类的str相当于A类的str,print时就会因为缺少name和age属性报错

  1. AttributeError: 'B' object has no attribute 'name'

有两种方法调用父类的构造函数

  1. class A:
  2. def __init__(self, name, age):
  3. self.name = name
  4. self.age = age
  5. def __str__(self):
  6. return self.name + str(self.age)
  7. class B(A):
  8. def __init__(self):
  9. # A.__init__(self,'weidiao',23)
  10. super(B,self).__init__('weidiao',23)
  11. b = B()
  12. print(b)

这两种方法第一种方法比较灵活,完全可以取代第二种方法。

A.__init__(self,args)这种方式只初始化了父类A

super(B,self).__init__(self,args)这种方式初始化了第一个父类(根据继承的顺序),所以这种方式是完全可以用FirstFather.__init()进行取代的。

九、单例

Java中的对象的创建和对象的初始化这两个过程是紧密耦合在一起的,对象创建过程指的是为对象分配必要的内存空间,对象初始化指的是向内存中写入值。简言之,Java中一旦调用构造函数,对象空间开辟和对象初始化两种操作就同时完成了。在Java中,单例只创建一次且只初始化一次。

在Python中不是这样,Python中对象创建过程和对象初始化过程是分开的。class的__new__()函数负责对象的创建,class的__init__()负责对象的初始化。在Python中,单例可能创建一次,初始化多次。

下面看一种单例的写法:

  1. class Dog:
  2. dog = None
  3. def __new__(cls, *args, **kwargs):
  4. if cls.dog is None:
  5. cls.dog = object.__new__(cls)
  6. print('create singleton over')
  7. return cls.dog
  8. def __init__(self, name):
  9. print('init is called')
  10. self.name = name
  11. # 下面这句话会报错,因为Dog.dog目前为None
  12. # print(Dog.dog.name)
  13. x = Dog('x')
  14. y = Dog('y')
  15. print(x.name) # y
  16. print(y.name) # y

此例中,会发现init is called输出两次,但是x和y实际上是同一个对象。也就是说,在Python中,只要调用对象的构造函数,必然会先调用__new__()函数,__new__()返回一个对象,然后Python会自动调用返回对象的__init__()函数。

上面例子的另一种实现是把重写new函数的工作放到一个父类里面,这样就能够实现:只需要继承父类就能够让自己变成单例。

  1. class Singleton:
  2. _instance = None
  3. def __new__(cls, *args, **kwargs):
  4. if not cls._instance:
  5. cls._instance = object.__new__(cls)
  6. return cls._instance
  7. class Dog(Singleton):
  8. def __init__(self, name):
  9. self.name = name
  10. x = Dog('x')
  11. y = Dog('y')
  12. print(x.name, y.name)

在Python中,我们创建的任何一个对象,无需重写setattr方法即可随便往对象上“悬挂”成员变量。

  1. class Ha:
  2. pass
  3. x = Ha()
  4. x.dog = 3
  5. print(x.dog)

单例的实现

  1. from functools import lru_cache
  2. class Singleton:
  3. @lru_cache()
  4. def __new__(cls, *args, **kwargs):
  5. obj = object.__new__(cls)
  6. obj.inited = False
  7. return obj
  8. class Haha(Singleton):
  9. def __init__(self, name):
  10. if self.inited:
  11. return
  12. self.inited = True
  13. self.name = name
  14. print("inited")
  15. x = Haha("x")
  16. y = Haha("y")
  17. print(x.name)
  18. print(y.name)

总结

在语言的完美、统一程度上,Python无人可及,Java都比它差一点。

Python面向对象几个知识点的更多相关文章

  1. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  2. python 面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  3. python 面向对象学习

    ------Python面向对象初 下面写一个类的简单实用,以便方便理解类 #python 3.5环境,解释器在linux需要改变 #阅读手册查询readme文件 #作者:S12-陈金彭 class ...

  4. Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)

    Python开发[第七篇]:面向对象   详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇)   上一篇<Python 面向对象(初级篇)> ...

  5. python 面向对象进阶之内置方法

    一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...

  6. 【转】python 面向对象(进阶篇)

    [转]python 面向对象(进阶篇) 上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 ...

  7. python 面向对象(进阶篇)转载武沛齐

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  8. Python 面向对象 (进阶篇)

    <Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可 ...

  9. python 面向对象初级篇

    Python 面向对象(初级篇) 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发" ...

随机推荐

  1. python3 验证码图片切割

    切割前图片 切割后四个图片 代码 #coding:utf8 import os from PIL import Image,ImageDraw,ImageFile import numpy impor ...

  2. 【中文分词系列】 4. 基于双向LSTM的seq2seq字标注

    http://spaces.ac.cn/archives/3924/ 关于字标注法 上一篇文章谈到了分词的字标注法.要注意字标注法是很有潜力的,要不然它也不会在公开测试中取得最优的成绩了.在我看来,字 ...

  3. OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)

    顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的 ...

  4. hadoop环境搭建与測试

    搭建參看: http://blog.csdn.net/w13770269691/article/details/16883663/ 查看集群状态: [root@master bin]# hdfs df ...

  5. Android:安装时提示:INSTALL_FAILED_INSUFFICIENT_STORAGE

    在将程序发布到手机上时提示该错误: INSTALL_FAILED_INSUFFICIENT_STORAGE 解决方法: 1. adb shell 2. #df # df df Filesystem   ...

  6. Discuz常见小问题-如何批量加精,置顶帖子

    批量选中帖子,然后置顶和精华都可以勾选 完成之后的效果

  7. jQuery函数的等价原生函数代码示例

    选择器 jQuery的核心之一就是能非常方便的取到DOM元素.我们只需输入CSS选择字符串,便可以得到匹配的元素.但在大多数情况下,我们可以用简单的原生代码达到同样的效果. .代码如下: //---- ...

  8. ZH奶酪:Ubuntu 14.04配置LAMP(Linux、Apache、MySQL、PHP)

    ZH奶酪:Ubuntu 14.04安装LAMP(Linux,Apache,MySQL,PHP) 之前已经介绍过LAMP的安装,这边文章主要讲解一下LAMP的配置. 1.配置Apache (1)调整Ke ...

  9. Excel 2007 若干技巧。

    1.自定义序列 office按钮→excel选项→常用→编辑自定义列表 2.无法清空剪贴板错误的处理办法: 取消"显示粘贴选项"选项 3.每次选定同一单元格 输入后按ctrl+En ...

  10. miniOrm

    PetaPoco.Core https://www.nuget.org/packages/PetaPoco.Core/5.1.228