博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python之类
阅读量:5321 次
发布时间:2019-06-14

本文共 8224 字,大约阅读时间需要 27 分钟。

1. 类属性

特殊的类属性

C.__name__ 类C的名字(字符串)

C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module__ 类C定义所在的模块(1.5 版本新增)
C.__class__ 实例C对应的类(仅新式类中)

 

 

2. 实例属性

实例仅有两个特殊属性

__class__ 实例的类

__dict__ 实例的属性

>>> class C(object):    pass    >>> c = C()>>> c.foo = 1>>> c.bar = 2>>> c.__dict__{
'foo': 1, 'bar': 2}>>> c.__class__

 

使用__slots__限制实例添加属性

class Student(object):    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称>>> s = Student() # 创建新的实例>>> s.name = 'Michael' # 绑定属性'name'>>> s.age = 25 # 绑定属性'age'>>> s.score = 99 # 绑定属性'score'Traceback (most recent call last):  File "
", line 1, in
AttributeError: 'Student' object has no attribute 'score'

 

 

实例属性 vs 类属性

类和实例都是名称空间。类是类属性的名称空间,实例则是实例属性的。可采用类来访问类属性,如果实例没有同名属性,则也可用实例来访问。

但修改类属性要使用类名,而不是实例名

>>> class C(object):    version = 1.0 >>> c = C()>>> C.version1.0>>> c.version1.0>>> c.version += 0.1    # 创建了一个实例属性version, 覆盖了同名类属性>>> c.version1.1>>> C.version1.0>>> C.version += 0.1>>> C.verison1.1>>> c.version1.1      # 类属性的修改会影响到所有实例

 

 

补充:Python 没有提供任何内部机制来跟踪一个类有多少个实例被创建了, 但可以通过一个类属性来记录实例的个数。

class Hello(object):    count = 0    def __init__(self):        Hello.count += 1    def __del__(self):        Hello.count -= 1        >>> a = Hello()>>> b = Hello()>>> Hello.count2>>> del a>>> Hello.count1

 

 

 

3. classmethod 、 staticmethod 、@property 

@property 

class Student(object):  #birth是可读写属性(多定义了一个setter的装饰器),而age就是一个只读属性      @property      def birth(self):          return self._birth       @birth.setter      def birth(self, value):          self._birth = value       @property      def age(self):          return 2014 - self._birth    ---------------------------------      >>>s = Student()  >>>s.birth = 2000  >>>s.birth  2000  >>>s.age14

 

@classmethod 和 @staticmethod都可以让直接以类方式访问某个内置函数。但@classmethod要求的第一个参数为cls(即类自身,而不是实例自身(实例自身用self))

@classmethod 的函数可以在类中继承,而@staticmethod不行。

class Date(object):      def __init__(self, month, day, year):          self.month = month          self.day   = day          self.year  = year       @staticmethod      def millenium_1(month, day):          return Date(month, day, 2000)       @classmethod      def millenium_2(cls, month, day):          #cls is an object that holds class itself          return cls(month, day, 2000)    class DateTime(Date):      def display(self):          return "{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)    new_year = Date(1, 1, 2013)               millenium_new_year_1 = Date.millenium_1(1, 1)  millenium_new_year_2 = Date.millenium_2(1, 1)  isinstance(new_year, Date) # True  isinstance(millenium_new_year_1, Date) # Trueisinstance(millenium_new_year_2, Date) # True    datetime1 = DateTime(10, 10, 1990)  datetime2 = DateTime.millenium_1(10, 10)  datetime3 = DateTime.millenium_2(10, 10)  isinstance(datetime1, DateTime) # True  isinstance(datetime2, DateTime) # False  isinstance(datetime2, DateTime) # True

 

 

 

4. 类的继承

一般没有什么可以继承时,继承object(采用新式类)。

如果有同名属性,则子类的属性会覆盖基类的属性(__doc__属性不会继承),但可以用super显示调用基类属性。

>>> class P(object):    def __init__(self):        print "It's P"        >>> class C(P):    def __init__(self):        print "It's C"        >>> c = C()It's C>>> class C(P):    def __init__(self):        super(C, self).__init__()        print "It's C"        >>> c = C()It's PIt's C

 

4.1 从标准类型派生

 

 

4.2 多重继承

class P1(object): # parent class 1 父类1    def foo(self):        print 'called P1-foo()'class P2(object): # parent class 2 父类2    def foo(self):        print 'called P2-foo()'class C1(P1, P2): # child 1 der. from P1, P2 #子类1,从P1,P2派生    passclass C2(P1, P2): # child 2 der. from P1, P2 #子类2,从P1,P2派生    def bar(self):        print 'called C2-bar()'class GC(C1, C2): # define grandchild class #定义子孙类    pass # derived from C1 and C2 #从C1,C2派生# 新式类采用广度优先的继承方式>>> gc = GC()>>> gc.foo() # GC ==> C1 ==> C2 ==> P1called P1-foo()>>> gc.bar() # GC ==> C1 ==> C2called C2-bar()# 但如果是经典类, 即P1,P2不是继承object, 则采用深度优先,从左至右的继承方式>>> gc = GC()>>> gc.foo() # GC ==> C1 ==> P1called P1-foo()>>> gc.bar() # GC ==> C1 ==> P1 ==> P2called P2-bar()

 

 

 

5. 类、实例和其他对象的内建函数

issubclass()

isinstance()
hasattr()、getattr()、setattr()、delattr()
dir()
super()
vars() # 同__dict__

 

6. 定制类

 

6.1  __str__、 __repr__

class Student(object):    def __init__(self, name):        self.name = name    def __str__(self):        return 'Student object (name=%s)' % self.name    __repr__ = __str__>>>print Student('David')>>>Student('David')----------------Student object (name=David)    #__str__Student object (name=David)    #__repr__

 

6.2 __getattr__

class Student(object):    def __init__(self, name):        self.name = 'Michael'    def __getattr__(self, attr):        if attr=='score':            return 99>>>student = Student('David')>>>student.name>>>student.score>>>print student.grade---------------'David'99None    #可以让class只响应特定的几个属性(通过抛出AttributeError的错误)

 

6.3 __iter__

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

class Fib(object):    def __init__(self):        self.a, self.b = 0, 1 # 初始化两个计数器a,b    def __iter__(self):        return self # 实例本身就是迭代对象,故返回自己    def next(self):        self.a, self.b = self.b, self.a + self.b # 计算下一个值        if self.a > 1000: # 退出循环的条件            raise StopIteration();        return self.a # 返回下一个值>>> for n in Fib():...     print n,------------------------1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

 

6.4 __getitem__

class Fib(object):    def __getitem__(self, n):        a, b = 1, 1        for x in range(n):            a, b = b, a + b        return a------------------------->>> f = Fib()>>> f[0]1>>> f[1]1>>> f[2]2>>> f[10]89>>> f[100]573147844013817084101

 

6.5 __call__

而且通过callable()函数,我们就可以判断一个对象是否是“可调用”对象

class Student(object):    def __init__(self, name):        self.name = name    def __call__(self):        print('My name is %s.' % self.name)>>>student = Student('Daivd')>>>student()---------------------My name is David.

 

 

 

7. 私有化

名称前的单下划线

名称前的单下划线,用于指定该名称属性为“私有”。这有点类似于惯例,为了使其他人(或你自己)使用这些代码时将会知道以“_”开头的名称只供内部使用。正如Python文档中所述:

以下划线“_”为前缀的名称(如_spam)应该被视为API中非公开的部分(不管是函数、方法还是数据成员)。此时,应该将它们看作是一种实现细节,在修改它们时无需对外部通知。

 

名称前的双下划线

名称(具体为一个方法名)前双下划线(__)的用法并不是一种惯例,对解释器来说它有特定的意义。

Python中的这种用法是为了避免与子类定义的名称冲突。Python文档指出,“__spam”这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被“_classname__spam”这种形式原文取代,在这里“classname”是去掉前导下划线的当前类名。

>>> class A(object): ... def _internal_use(self): ...     pass... def __method_name(self): ...     pass... >>> dir(A()) ['_A__method_name', ..., '_internal_use']>>> class B(A): ... def __method_name(self): ... pass... >>> dir(B()) ['_A__method_name', '_B__method_name', ..., '_internal_use']

 

 

 

8. 元类

metaclasses are what create these objects.They are the classes' classes.

任何子类可以通过metaclass扫描映射关系,并存储到基类的class中。(往往用于那些需要动态创建类的场合,如orm)

 

type

type is the metaclass Python uses to create all classes behind the scenes.

age = 35age.__class__#
age.__class__.__class__#

 

自定义metaclass

The main purpose of a metaclass is to change the class automatically, when it's created. You usually do this for APIs, where you want to create classes matching the current context.  A typical example of this is the Django ORM.

当用户定义一个类时,Python解释器首先在当前类的定义中查找__metaclass__,如果没有找到,就继续在父类中查找,找到了,就使用父类中定义的__metaclass__来创建,也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。

class UpperAttrMetaclass(type):     # __new__ is the method called before __init__    # it's the method that creates the object and returns it    # while __init__ just initializes the object passed as parameter    # you rarely use __new__, except when you want to control how the objectis created.    # here the created object is the class, and we want to customize it, so we override __new__    # you can do some stuff in __init__ too if you wish    # some advanced use involves overriding __call__ as well    def __new__(cls, clsname, bases, dct):        uppercase_attr = {}        for name, val in dct.items():            if not name.startswith('__'):                uppercase_attr[name.upper()] = val            else:                uppercase_attr[name] = val        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)

 

__new__接收到的参数依次是:

  1. 当前准备创建的类的对象

  2. 类的名字

  3. 类继承的父类集合

  4. 类的方法集合

 

 

 

 2015-06-01

转载于:https://www.cnblogs.com/whuyt/p/4538243.html

你可能感兴趣的文章
JS apply的巧妙用法以及扩展到Object.defineProperty的使用
查看>>
sha1加密java代码
查看>>
hibernate 多对多双向关联
查看>>
Mysql自带的年月日函数
查看>>
源码实现 --> strcmp
查看>>
Js获取下拉框当前选择项的文本和值
查看>>
BtxCMS.Net 项目
查看>>
KVO讲解
查看>>
centOS7 下安装smb服务器
查看>>
toLocaleString
查看>>
易普优APS高级计划排程系统系列提纲:行业知识,业务建模,排程算法,计划可视化,平台框架,案例分享...
查看>>
面试题-链表
查看>>
Opencv Hello World
查看>>
总有一天你将破蛹而出
查看>>
java final关键字
查看>>
css实现单行和多行文本溢出显示省略号
查看>>
JavaScript核心--Function
查看>>
jmeter 创建web测试计划
查看>>
To change for better
查看>>
在IE浏览器下,PDF将弹出窗口遮挡了
查看>>