类的详解

面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用。
类是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)。
对象,根据模板创建的实例(即对象),实例用于调用被包装在类中的函数。类是对象的定义 ,而实例是“ 真正的实物”,它存放了类中所定义的对象的具体信息。
面向对象三大特性:封装、继承和多态。

1、类的定义:

1、使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:

class ClassName:'类的帮助信息'   #类文档字符串class_suite    #类体#类的帮助信息可以通过ClassName.__doc__查看。
#class_suite 由类成员,方法,数据属性组成。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Employee:'所有员工的基类'empCount = 0def __init__(self, name, salary):self.name = nameself.salary = salaryEmployee.empCount += 1def displayCount(self):print "Total Employee %d" % Employee.empCountdef displayEmployee(self):print "Name : ", self.name,  ", Salary: ", self.salary#empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。
#第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
#self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
实例

2、self代表类的实例,而非类。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

class Test:def prt(self):print(self)print(self.__class__)t = Test()
t.prt()'''
以上实例执行结果为:
<__main__.Test instance at 0x10d066878>
__main__.Test从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.__class__ 则指向类。
'''#self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
class Test:def prt(runoob):print(runoob)print(runoob.__class__)
t = Test()
t.prt()'''
以上实例执行结果为:
<__main__.Test instance at 0x10d066878>
__main__.Test
'''
self
''' 创建实例对象
实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。
以下使用类的名称 Employee 来实例化,并通过 __init__ 方法接收参数。'''#"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
#"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)''' 访问属性
您可以使用点号 . 来访问对象的属性。使用如下类的名称访问类变量:'''emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount''' 可以使用以下函数的方式来访问属性:
getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。'''
属性访问

2、类的成员

1、字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。普通字段属于对象,静态字段属于类。

#coding=utf-8
class Province:# 静态字段country = '中国'def __init__(self, name):# 普通字段self.name = name
# 直接访问普通字段
obj = Province('河北省')
print(obj.name)
# 直接访问静态字段
print(Province.country)'''
由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的。其静态字段在内存中只保存一份,普通字段在每个对象中都要保存一份。
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段。
'''
字段

2、类的方法包括实例方法、类方法、静态方法。

class Foo(object):  def test(self)://定义了实例方法  print("object")  @classmethod  def test2(clss)://定义了类方法  print("class")  @staticmethod  def test3()://定义了静态方法  print("static")  
方法
#coding=utf-8
class Apple:def fun1(self):return 'normal'@staticmethoddef fun2():return 'staticmethod'@classmethoddef fun3(cls):return 'classmethod'
print Apple.fun1
print Apple.fun2
print Apple.fun3
print "-"*80apple = Apple()
print apple.fun1
print apple.fun2
print apple.fun3
print "-"*80apple1 = Apple()
print apple1.fun1
print apple1.fun2
print apple1.fun3'''
输出结果:
1、<unbound method Apple.fun1>
2、<function fun2 at 0x00000000022FC4A8>
3、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>>
4、----------------------------------------------------------------------------
5、<bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE08>>
6、<function fun2 at 0x00000000022FC4A8>
7、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>>
8、----------------------------------------------------------------------------
9、 <bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE48>>
10、<function fun2 at 0x00000000022FC4A8>
11、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>>
--------------------- ------------------------------------------------------
''''''
解析:
1、普通方法传入的第一个参数必须是self(当然也可以不用self,官方要求尽量用self),self是指实例对象本身;
2、静态方法无需传参;
3、类方法传入的第一个参数必须是class,是指类本身。
对比结果1,5,9行: 
fun1通过class调用时,它是未绑定的方法,而实例化apple和apple1之后,它属于绑定的方法,且实例化后的apple和apple1内存地址不同,因为它们属于不同的实例对象。
对比结果2,6,10行: 
静态方法fun2通过class调用或者通过实例化后的对象调用,是没有任何区别的,全部都是指向同一块内存地址。可以简单的理解成静态方法与类或者实例没有任何关系,一旦调用后,它的内存地址即确定。
对比结果3,7,11行: 
类方法fun3通过class调用或者通过实例化后的对象调用,是没有任何区别的,全部都是指向同一块内存地址。为什么?因为实例化对象apple和apple1调用类方法fun3传入的第一个参数是类本身Apple,也就是说apple.fun3 = apple1.fun3 = Apple.fun3。区别总结:
1、静态方法装饰器下定义的方法属于函数(function);
2、类方法装饰器下定义的方法属于方法(method);
3、静态方法无需传入任何参数;
4、类方法传入的第一个参数必须是class本身cls;
5、静态方法与类方法一旦被调用,内存地址即确定。通过类调用和通过实例化对象调用的结果完全一样。
6、三种方法从不同层次上来对方法进行了描述:实例方法针对的是实例,类方法针对的是类,他们都可以继承和重新定义,而静态方法则不能继承,可以认为是全局函数
'''
实例解析

3、如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。

#coding=utf-8
# ############### 定义 ###############
class Foo:def func(self):pass# 定义属性
    @propertydef prop(self):pass
# ############### 调用 ###############
foo_obj = Foo()
foo_obj.func()
foo_obj.prop   #调用属性'''
由属性的定义和调用要注意一下几点:
定义时,在普通方法的基础上添加 @property 装饰器;
定义时,属性仅有一个self参数
调用时,无需括号方法:foo_obj.func()属性:foo_obj.prop
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能
'''
属性

属性的两种定义方式
属性的定义有两种方式:
装饰器 即:在方法上应用装饰器
静态字段 即:在类中定义值为property对象的静态字段

'''
装饰器方式
装饰器方式:在类的普通方法上应用@property装饰器
我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
经典类,具有一种@property装饰器(如上一步实例)
'''# ############### 定义 ###############    
class Goods:@propertydef price(self):return "wupeiqi"
# ############### 调用 ###############
obj = Goods()
result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值#新式类,具有三种@property装饰器
# ############### 定义 ###############
class Goods(object):@propertydef price(self):print '@property'@price.setterdef price(self, value):print '@price.setter'@price.deleterdef price(self):print '@price.deleter'
# ############### 调用 ###############
obj = Goods()
obj.price      # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price= 123 # 自动执行 @price.setter修饰的price方法,并将123赋值给方法的参数
del obj.price  # 自动执行 @price.deleter 修饰的 price 方法'''
注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
'''
装饰器方式
#静态字段方式,创建值为property对象的静态字段
#当使用静态字段的方式创建属性时,经典类和新式类无区别class Foo:def get_bar(self):return 'good'BAR = property(get_bar)
obj = Foo()
reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
print result'''
property的构造方法中有个四个参数
第一个参数是方法名,调用 对象.属性 时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
'''
静态字段方式

 3、新式类和旧式类

# -*- coding: utf-8 -*-
# 经典类或者旧试类
class A:pass
a = A()# 新式类
class B(object):pass
b = B()# python2不支持
# print(A.__class__)
print(a.__class__)
print(type(A))
print(type(a))# python2
# __main__.A
# <type 'classobj'>
# <type 'instance'># python3
# <class 'type'>
# <class '__main__.A'>
# <class 'type'>
# <class '__main__.A'>print(B.__class__)
print(b.__class__)
print(type(B))
print(type(b))# python2
# <type 'type'>
# <class '__main__.B'>
# <type 'type'>
# <class '__main__.B'># python3
# <class 'type'>
# <class '__main__.B'>
# <class 'type'>
# <class '__main__.B'># 旧式类的实现不够好,类是类,实例是实例,类的类型是classobj,实例的类型是instance,两者的联系只在于__class__,
# 这和内置对象是不同的,int对象的类型就是int,同时int()返回的也是int类型的对象,内置对象和自定义对象不同就对代码统一实现带来很大困难。
#
# 新式类
#
# 1. 所有类的类型都是type
# 2. 所有类调用的结果都是构造,返回这个类的实例
# 3. 所有类都是object的子类
# 4. 新式类不仅可以用旧类调用父类的方法,也可以用super方法。
View Code

 4、类的私有成员

1):单下划线_开头:只是告诉别人这是私有属性,外部依然可以访问更改
2):双下划线__开头:外部不可通过实例化对象.属性名来访问或者更改
实际将其转化为了_类名_属性名,只是在内部将变量名修改了,我们仍让可以通过._类名_属性名访问

>>>class Test():
>>>    a = 100
>>>Test.__dict__
Out[3]: {'__doc__': None, '__module__': '__main__', 'a': 100}>>>class Test():
>>>    __a = 100
>>>Test.__dict__
Out[5]: {'_Test__a': 100, '__doc__': None, '__module__': '__main__'}
>>>Test._Test__a
Out[6]: 100
实例

私有成员和公有成员的访问限制不同:
1) 静态字段
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问;
2) 普通字段
公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
私有普通字段:仅类内部可以访问;
注意:如果想要强制访问私有字段,可以通过【对象._类名__私有字段明】访问(如:obj._C__foo),不建议强制访问私有成员。方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用

5、类成员的修改

1、修改类的对象(实例)属性

#coding=utf-8
class Test(object):a = 100def __init__(self):pass
t1 = Test()
t2 = Test()
#1.通过实例对象t1修改类属性的值
print("修改前:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))
t1.a += 100
print("修改后:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))'''
输出:
修改前:t1.a = 100, t2.a = 100, Test.a = 100 
修改后:t1.a = 200, t2.a = 100, Test.a = 100
'''
View Code

很明显,我们通过实例对象修改类属性的值,并没有在全局范围奏效,它只是对t1对象的实例属性修改了,实际上并没有对本身定义的类属性和其它的对象的属性造成变动。

2、修改类的属性:

class Test(object):a = 100def __init__(self):pass
t1 = Test()
t2 = Test()
#1.通过类名修改类属性的值
print("修改前:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))
Test.a += 100
print("修改后:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))'''
输出: 
修改前:t1.a = 100, t2.a = 100, Test.a = 100 
修改后:t1.a = 200, t2.a = 200, Test.a = 200
'''
View Code

通过类名修改的类属性,在全局范围奏效,也就是说确实修改了类属性的值,在实例对象中我们看到属性值全部被修改。

6、类的内置特殊成员

#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'
obj = Province('HeBei',10000)   # 自动执行类中的 __init__ 方法
print obj      
'''
#__init__构造方法,通过类创建对象时,自动触发执行。输出:
<__main__.Province instance at 0x0000000003989108>
'''
__init__
#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self):          #当对象在内存中被释放时,自动触发执行。pass
obj = Province('HeBei',10000)   
print obj      
'''
#__del__析构方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。输出:
<__main__.Province instance at 0x0000000003989108>
'''
__del__
#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self):passdef __call__(self):print "__call__"
obj = Province('HeBei',10000)   
print obj()             #对象后面加括号,触发执行。
'''
#__call__构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()输出:
__call__
None
'''
__call__
#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self):passdef __call__(self):print "__call__"def __str__(self):return("__str__")
obj = Province('HeBei',10000)   
print obj    '''
#__str__如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。输出:
__str__
'''
__str__
#用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__。
#a)第一步
class Foo(object):pass
obj = Foo()
for i in obj:print i
# 报错:TypeError: 'Foo' object is not iterable#b)    第二步
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):   def __iter__(self):pass
obj = Foo()
for i in obj:print i
# 报错:TypeError: iter() returned non-iterator of type 'NoneType'#c)    第三步
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):def __init__(self, sq):self.sq = sqdef __iter__(self):return iter(self.sq)
obj = Foo([11,22,33,44])
for i in obj:
print i#d)For循环语法内部
#!/usr/bin/env python
# -*- coding:utf-8 -*-
obj = iter([11,22,33,44])
while True:val = obj.next()print val
__iter__
#coding=utf-8
class Foo(object):def __getitem__(self, key):print('__getitem__', key)def __setitem__(self, key, value):# print('__setitem__', key, value)self.key = keyself.value = valueprint(key,value)return self.keydef __delitem__(self, key):print('__delitem__', key)obj =Foo()
result = obj['k1']       # 自动触发执行 __getitem__
obj['k3']='xxxxxx'      # 自动触发执行 __setitem__
del obj['k1']               # 自动触发执行 __delitem__
__getitem__、__setitem__、__delitem__
#该三个方法用于分片操作,如:列表。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):def __getslice__(self, i, j):print '__getslice__',i,jdef __setslice__(self, i, j, sequence):print '__setslice__',i,jdef __delslice__(self, i, j):print '__delslice__',i,j
obj = Foo()
obj[-1:1]                               # 自动触发执行 __getslice__
obj[0:1] = [11,22,33,44]      # 自动触发执行 __setslice__
del obj[0:2]                          # 自动触发执行 __delslice__
__getslice__、__setslice__、__delslice__
'''
__new__()在Python :类里面的构造方法init()负责将类的实例化,而在init()调用之前,new()决定是否要使用该init()方法,
因为new()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。
如果将类比喻为工厂,那么init()方法则是该工厂的生产工人,init()方法接受的初始化参 数则是生产所需原料,init()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 new()则是生产部经理,new()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。
new()方法的特性:
new()方法是在类准备将自身实例化时调用。
new()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
''''''
通常来说,新式类开始实例化时,new()方法会返回cls(cls指代当前类)的实例,然后该类的 init()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入new ()方法中接收的位置参数和命名参数。
注意:如果new()没有返回cls(即当前类)的实例,那么当前类的init()方法是不会被调用 的。
如果new()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。
'''
class Foo(object):def __init__(self, *args, **kwargs):passdef __new__(cls, *args, **kwargs):return object.__new__(Stranger, *args, **kwargs) #重写Foo类的new方法,返回Stranger类的实例class Stranger(object):passfoo = Foo()
print(type(foo)) #结果显示foo其实是Stranger类的实例 <class '__main__.Stranger'>#链接:https://blog.csdn.net/Four_Infinite/article/details/52798919#__init__与__new__的先后执行顺序
class Test(object):def __init__(self,name):self.name = nameprint "hey"def __new__(cls, *args, **kwargs):print "hello"return object.__new__(cls, *args, **kwargs)
f = Test("study")'''
输出:hellohey
'''
__new__
#阅读以下代码:
class Foo(object):def __init__(self):pass 
obj = Foo()   # obj是通过Foo类实例化的对象'''
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
print type(obj) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type 'type'>              表示,Foo类对象由 type 类创建
所以,obj对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
'''#那么,创建类就可以有两种方式:
#a)    普通方式
class Foo(object):def func(self):print 'hello wupeiqi'
#b)    特殊方式(type类的构造函数)
def func(self):print 'hello wupeiqi'
Foo = type('Foo',(object,), {'func': func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员'''
==》 类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
'''
__metaclass__
'''
__new__ is the method called before __init__
It's the function that actually creates the object and returns it.
__init__ only initialize the object passed as a parameter.
We rarely use __new__, except when we want to control how the object
is created.
For a metaclass, the object created is a class. And since we want to 
customize it, we need to override __new__.
We can also do something by overriding __init__ to get customized initialization
process as well.
Advanced usage involves override __call__, but we won't talk about this here.'''
#链接:https://www.jianshu.com/p/224ffcb8e73e
#链接:https://www.jianshu.com/p/14b8ebf93b73
__new__ and __init__
class Test(type):pass
class Name(object):__metaclass__ = Testf = Name()
print type(f)
print type(Name)
print type(Test)'''
输出:<class '__main__.Name'><class '__main__.Test'><type 'type'>
'''class Test(type):def __init__(self,*args,**kwargs):super(Test,self).__init__(*args,**kwargs)def test(self,name):return name
class Name(object):__metaclass__ = Testdef __init__(self,what):self.what = whatdef sayhi(self):return self.whatf = Name("cat")
print type(f)
print type(Name)
print type(Test)'''
输出:<class '__main__.Name'><class '__main__.Test'><type 'type'>
'''
__metaclass__2
class Fo():passclass FFo(object):passprint type(Fo)
print type(type(Fo))
print type(FFo)'''
输出:<type 'classobj'><type 'type'><type 'type'>
'''
新旧类的type类型区别

 

#__doc__表示类的描述信息
#__module__表示当前操作的对象在那个模块,类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
#__class__表示当前操作的对象的类是什么
#__name__表示类名
#__bases__类的所有父类构成元素(包含了一个由所有父类组成的元组)
#__dict__表示类或对象中的所有成员(包含一个字典,由类的数据属性组成)。

#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'
print Province.__doc__
print Province.__module__
#print Province.__class__    #AttributeError: class Province has no attribute '__class__'
print Province.__name__
print Province.__bases__
print Province.__dict__'''
#__doc__表示类的描述信息
#__module__表示当前操作的对象在那个模块,类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
#__class__表示当前操作的对象的类是什么
#__name__表示类名
#__bases__类的所有父类构成元素(包含了一个由所有父类组成的元组)
#__dict__表示类的属性(包含一个字典,由类的数据属性组成)输出:
Genius is thing but labor and diligence!
__main__
Province
()
{'country': 'China', '__module__': '__main__', 'func': <function func at 0x000000000329C358>, '__doc__': 'Genius is thing but labor and diligence!', '__init__': <function __init__ at 0x000000000329C2E8>}'''
类的特殊成员
#coding=utf-8
class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'
obj = Province('HeBei',10000)
print obj.__doc__ 
print obj.__module__
print obj.__class__  
#print obj.__name__    #AttributeError: Province instance has no attribute '__name__'  
#print obj.__bases__   #AttributeError: Province instance has no attribute '__bases__'
print obj.__dict__'''
#__doc__表示类的描述信息
#__module__表示当前操作的对象在那个模块,类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
#__class__表示当前操作的对象的类是什么
#__name__表示类名
#__bases__类的所有父类构成元素(包含了一个由所有父类组成的元组)
#__dict__表示类的属性(包含一个字典,由类的数据属性组成)输出:
Genius is thing but labor and diligence!
__main__
__main__.Province
{'count': 10000, 'name': 'HeBei'}
'''
类的实例特殊成员

7、类的继承

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

'''
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。继承概念的实现方式主要有2类:实现继承、接口继承。
实现继承是指使用基类的属性和方法而无需额外编码的能力。
接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法)。
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
'''
#coding=utf-8class Person(object):   # 定义一个父类def talk(self):    # 父类中的方法print("person is talking....")  class Chinese(Person):    # 定义一个子类, 继承Person类def walk(self):      # 在子类中定义其自身的方法print('is walking...')c = Chinese()
c.talk()      # 调用继承的Person类的方法
c.walk()     # 调用本身的方法'''
# 输出
person is talking....
is walking...
'''
View Code
"""
如果我们要给实例 c 传参,我们就要使用到构造函数,那么构造函数该如何继承,同时子类中又如何定义自己的属性?
继承类的构造方法:1.经典类的写法: 父类名称.__init__(self,参数1,参数2,...)2. 新式类的写法:super(子类,self).__init__(参数1,参数2,....)
"""#coding=utf-8
class Person(object):def __init__(self, name, age):self.name = nameself.age = ageself.weight = 'weight'def talk(self):print("person is talking....")class Chinese(Person):def __init__(self, name, age, language):  # 先继承,在重构Person.__init__(self, name, age)  #继承父类的构造方法,也可以写成:super(Chinese,self).__init__(name,age)self.language = language    # 定义类的本身属性def walk(self):print('is walking...')class American(Person):pass
c = Chinese('bigberg', 22, 'Chinese')
构造函数的继承
class Person(object): def __init__(self, name, age):self.name = nameself.age = ageself.weight = 'weight'def talk(self):print("person is talking....")class Chinese(Person):def __init__(self, name, age, language): Person.__init__(self, name, age) self.language = languageprint(self.name, self.age, self.weight, self.language)def talk(self):  # 子类 重构方法print('%s is speaking chinese' % self.name)def walk(self):print('is walking...')c = Chinese('bigberg', 22, 'Chinese')
c.talk()'''
# 输出
bigberg 22 weight Chinese
bigberg is speaking chinese
'''
父类方法的重写

8、类的多态

多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。

"""
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话,对不同类的对象发出相同的消息将会有不同的行为。 
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。
"""
#一个抽象类具有多个子类,就是多种形态。多态依赖于继承,没有继承就没有多态。class Animal(object):def __init__(self, name, age):self.name = nameself.age = agepassclass Dog(Animal):def __init__(self, name, age, breed):super(Dog, self).__init__(name, age)self.breed = breedpassclass Cat(Animal):def __init__(self, name, age, breed):super(Cat, self).__init__(name, age)self.breed = breedpass#我们定义了一个 Animal类,又定义了其两个子类 :Dog 和 Cat。这两个子类就表示了Animal这个类的多种形态。
View Code

多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

9、对象销毁(垃圾回收)

要保持追踪内存中的对象,Python使用了引用计数这一简单技术。也就是说Python内部记录着所有使用中的对象 各有多少引用。一个内部跟踪变量,称为引用计数器。每个对象各有多少个引用,简称引用计数。当对象被创建时,就创建了一个引用计数,当这个对象不再需要时,也就是说,这个对象的引用计数变为0时,它被垃圾回收。(并不是100%这样)

链接:https://www.cnblogs.com/bigberg/p/7591463.html

转载于:https://www.cnblogs.com/windyrainy/p/10654862.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/394412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么情况不能办理房产抵押贷款 房产抵押贷能贷多少?

所谓房产抵押贷款是指以自己或亲友的房产作为抵押物向贷款机构申请贷款&#xff0c;款项可用于企业经营、买房、买车、装修及其他用途的融资方式。但是有些情况是规定不能申请房产抵押贷款的&#xff0c;而且贷款的数额是有限的&#xff0c;不是想贷多少就多少。那么&#xff0…

2数据库表增加一个字段_14个实用的数据库设计技巧!

1. 原始单据与实体之间的关系可以是一对一、一对多、多对多的关系。在一般情况下&#xff0c;它们是一对一的关系&#xff1a;即一张原始单据对应且只对应一个实体。在特殊情况下&#xff0c;它们可能是一对多或多对一的关系&#xff0c;即一张原始单证对应多个实体&#xff0c…

错误: 找不到或无法加载主类 helloworld_全面剖析虚拟机类加载机制

1.引言java源文件经过编译后生成字节码class文件&#xff0c;需要经过虚拟机加载并转换成汇编指令才能执行&#xff0c;那么虚拟机是如何一步步加载这些class文件的对于java程序员是完全透明的&#xff0c;本文尝试全面分析jvm类加载机制。2.思考开始之前我们来简单思考一下&am…

200道物理学难题——038蚱蜢跃树

转载于:https://www.cnblogs.com/hanford/p/6168514.html

strcmp可以比较数组么_大家都用过百度云,但你面试过百度云么

作者&#xff1a;黄小斜百度研发面经百度智能云软件研发工程师百度智能云研发岗好像是做控制台方面的组一面&#xff1a;1自我介绍&#xff0c;项目2 static关键字有什么用&#xff0c;static修饰不同东西时有什么作用&#xff0c;内部类用static修饰和不用static修饰有何区别。…

go kegg_KEGG分析及可视化

上一篇推文中我们解释了GO富集分析及可视化&#xff08;GO富集分析及可视化&#xff09;&#xff0c;除了GO富集分析&#xff0c;我们经常在paper中看到KEGG分析&#xff0c;KEGG是什么呢&#xff0c;Kyoto Encyclopedia of Genes and Genomes&#xff0c;京都基因和基因组百科…

IntelliJ IDEA注册码

IntelliJ IDEA注册码 http://idea.lanyus.com/ 1.导航栏下 2.help下 3.register点击 4.单选Activation code 5.粘贴注册码 转载于:https://www.cnblogs.com/YUJIE666/p/10662561.html

第十一次作业

1。题目&#xff1a; 输入一个字符串&#xff0c;统计大写字母、小写字母、空格、数字和其他字符的个数。(要求用字符数组 代码 #include<stdio.h> #define n 100 int main() {char a[n];int i,a10,b0,c0,d0;printf("输入字符串&#xff1a;\n");gets(a);for(i…

servlet中文乱码_10分钟快速掌握Servlet相关基础知识

Servlet的学习路线1、 创建Servlet2、 Servlet的相关配置3、 Servlet的生命周期4、 HttpServletRequest接口5、 HttpServletResponse接口6、 HttpSession接口7、 Filter、Listener接口Servlet的相关配置1、 创建Servlet extends HttpServlet2、 配置Serlvet第1种配置方式: web.…

python之collections之有序字典(OrderedDict)

一、定义OrderedDict是对字典的补充&#xff0c;它记住了字典元素的添加顺序。eg&#xff1a; 二、OrderedDict相关方法def clear(self): # real signature unknown; restored from __doc__ """     od.clear() -> None. Remove all items from od. …

进阶4:hive 安装

安装包&#xff1a; apache-hive-2.1.1-bin.tar.gz 安装步骤&#xff1a; 1.上传 apache-hive-2.1.1-bin.tar.gz 到linux; 2.解压文件&#xff1a; tar zxvf apache-hive-2.1.1-bin.tar.gz 3.安装mysql (仅支持mysql 5.7以下版本&#xff0c;不支持5.7或更高版本&#xff0c…

macbookpro接口叫什么_【科普】什么是雷电接口?苹果电脑MACBOOK PRO有吗?

刚接触笔记本的朋友不知道USB-C口是什么,也不知道雷电接口(Thunderbolt)是什么,只知道MACBOOK PRO有雷电3接口。简单来说 雷电接口是USB TYPE-C的替代模式,在此了解【什么是USB TYPE-C】 什么是雷电接口? 借用百度百科的表达 2011年2月24日,英特尔发布了长期以来广为宣传的…

usb serial port 驱动_tty初探 — uart驱动框架分析

写在前面&#xff1a;我们没有讲UART驱动&#xff0c;不过我们认为&#xff0c;只要系统学习了第2期&#xff0c;应该具备分析UART驱动的能力&#xff0c;小编做答疑几年以来&#xff0c;陆陆续续有不少人问到UART驱动怎么写&#xff0c;所以今天就分享一篇深度长文(17000字&am…

简述isodata算法的原理_算法常见面试题汇总(一):概率论与数理统计部分

初级或中级算法岗面试题主要有四类&#xff1a;数理统计基础、机器学习模型原理、编程能力、项目经验。项目经验因人而异&#xff0c;所以仅总结前三个方面的基础知识&#xff0c;分享给朋友。&#xff08;高级或资深算法岗面试内容不在本文范围内&#xff09;1.大数定律弱大数…

php开发支付宝支付密码忘记了怎么办_密码箱忘记密码怎么办?密码箱解锁方法大全...

密码箱忘记密码经常发生&#xff0c;有时候急着赶车赶飞机必须用的证件在密码行李箱&#xff0c;怎么办&#xff1f;破坏&#xff1f;当你忘记密码的时候千万不要着急&#xff0c;不要试着用暴力破坏密码锁。操作方法一此类型的密码箱的开锁方法。把箱子放在光线好的地方放平&a…

请写出至少5个html块元素标签_34道常见的HTML+CSS面试题(附答案)

公众号【传智播客博学谷】回复关键词&#xff1a;前端 PS Java(100G) Python(80G) 大数据 区块链 测试 PPT JS(40g300教程) HTML 简历 领取相关学习资料&#xff01;一、HTML1、标签上title属性与alt属性的区别是什么&#xff1f;alt属性是为了给那些不能看到你文档中图像的浏览…

[阅读笔记]Zhang Y. 3D Information Extraction Based on GPU.2010.

1.立体视觉基础 深度定义为物体间的距离 视差定义为同一点在左图(reference image) 和右图( target image) 中的x坐标差。 根据左图中每个点的视差得到的灰度图称为视差图。 那么根据三角几何关系可以由视差(xR - xT ) 计算出深度.bcamera基线距离&#xff0c;f焦距。 离相机越…

r语言 小树转化百分数_“小树”机器人1.0新品发布会

产品初衷伴随着AI的落地&#xff0c;从最开始的刷脸支付&#xff0c;再到自动驾驶&#xff0c;还是现在互联网的5G时代&#xff0c;AI无疑都是产业变革的核心动力。那么作为一家科技创新的企业&#xff0c;小树机器人从建立之初就在不断的创新&#xff0c;我们致力于从智能出发…

javascript对象包含哪些要素_让人迷糊的JavaScript对象(Object一)

对于很多初学的小伙伴听到JavaScript内置对象、BOM、DOM、WEB API等关键词基本上都是迷糊&#xff0c;不是很明白他们之间的关系&#xff0c;以及他们是如果建立联系的。虽然我们现在小伙伴在学VUE&#xff0c;React等框架能简化我们的操作&#xff0c;但是遇到一些基础的问题还…

被吐嘈的NodeJS的异常处理

被吐嘈的NodeJS的异常处理 许多人都有这样一种映像&#xff0c;NodeJS比较快&#xff1b; 但是因为其是单线程&#xff0c;所以它不稳定&#xff0c;有点不安全&#xff0c;不适合处理复杂业务&#xff1b; 它比较适合对并发要求比较高&#xff0c;而且简单的业务场景。 在Expr…