码迷,mamicode.com
首页 > 编程语言 > 详细

Python基础:Python类(真累~)

时间:2018-02-22 19:40:22      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:单词   inf   lin   new   dict   自定义   obb   row   存在   

类的声明:

一、类的属性

(私有属性和公有属性)

(类属性)

二、类的方法

(构造方法、析构方法、自定义方法、特殊成员方法)

(静态方法、类方法、类属性)

三、类的继承

(方法和属性的继承,方法的重构)

(抽象类,多重继承)

四、类的多态

(实现接口的重用)

五、类的特殊装饰

(@staticmethod、@classmethod、@property)

六、类的来源和原类(metaclass)

七、反射

  • 类的声明

    使用class声明类,建议类名单词首字母大写。

    “新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。

    新式类:

class Management(object):

    def add():
        pass

      经典类:

class Management:
    pass

 

 

 

  • 类的属性 

    类的属性就是类定义的变量值。

       公有属性:在类里直接定义的属性,它在类名下面直接定义。

                        调用:1、类中调用:类名.属性名 ,更改原公有属性值

                                   2、实例调用:实例.属性名

class Management(object):
    num = 10

    def add(self):
        Management.num +=10            # 类中调用公有属性并更改值,num=11
        pass

s1 = Management()
s2 = Management()

# 第一种情况:s1实例中调用公有属性,s2实例没有调用公有属性
s1.num +=1
Management.num += 2
"""
<结果>
s1不变,s2和Management都改变了
s1_num:11   s2_num:12   Manage_num:12
"""

# 第二种情况:先调用s1实例公有属性,再通过S1调用add更改,然后再使用类更改
s1.num +=1
s1.add()
Management.num += 2
"""
<结果>
先调用的s1实例num依然不变,s2和Management都被修改了
s1_num:11   s2_num:22   Manage_num:22

"""

 问题:为什么修改num的值以后,实例s1和实例s2会有不同的结果呢 ?

            因为公有属性查找的顺序是:先找实例的公有属性,没找到再找类里的公有属性

            可以这样理解:Management相当于一个微信群,num是群里发的一张照片,S1和S2是群里面的两个人。

            情况1:S1把照片存到本地,P了个双眼皮,S2说太难看了,我也不会P图,不保存。这个时候发照片的Management说我也觉得难看,把图撤回,重新发了一个P的图。S2就只能保存最新的图片。

            情况2:S1找到Management说你的图太丑了,重新改一下吧,Management说好!撤回图片修改了~

 

       私有属性:加两个下划线,__membername,编译的时候自动加上类名,变成_classname__membername,这种技术叫变量名压缩(mangling),以达到外部不能调用的目的。实际使用_classname__membername是可以调用的,但是不符合规定。标准方法是通过定义函数来获取。

class Classname(object):
 '''this is a demo!'''
 def __init__(self):
  self.__membername = 88

 def read_membername(self):            # 标准的外部访问方法,使用函数来读取私有属性。
  return self.__membername

s= Classname()
print(s._Classname__membername)
print(s.read_membername())
'''
<结果>
88
88
------像下面的调用,会出现AttributeError错误------
print(s.__membername)
'''

       类属性:  类自带的属性,需要注意的是实例化的类属性,和原类的类属性不同。用上面的例子作演示。

属性
作用
示例
结果
__doc__类的文档字符串print(s.__doc__)
print(Classname.__doc__)

this is a demo!

this is a demo!

__dict__类的属性组成的字典print(s.__dict__)
print(Classname.__dict__)

{'_Classname__membername': 88}

{'__init__':, '__module__': '__main__', '__doc__': '\nthis is a demo!\n', 'read_membername':}

__name__类的名字(字符串)##不能用于实例print(s.__name__ )
print(Classname.__name__ )


Classname

__bases__类的所有父类组成的元组#不能用于实例print(s.__bases__)
print(Classname.__bases__)


(,)为什么没有值?可能是编译器问题

__module__类所属的模块print(s.__module__)
print(Classname.__module__)
__main__
__main__
__class__类对象的类型print(s.__class__)
print(Classname.__class__)
待测
__slots__

限定类属性,在类属性位置定义

未在slots定义的属性都是非法属性

__slots__.('name','age','sexy')使用'name','age','sexy'的以外属性会报错

           

  • 类的方法

    类的方法就是类里面定义的函数。类的构造方法、析构方法、自定义类方法、静态方法、类方法、属性方法、特殊成员方法。

    构造方法:__init__

    实例化类的时候就会运行的函数。希望初始化的参数放置在init下面。(个人觉得,这个初始化参数可以是一切对象!)

class A(object):
 def instense(self):
  print("init obj A")
  
class B(object):
 def __init__(self, para):
  self.init_para = para
  self.obj_A = A()
  self.num = 1
 
 def show(self):
  print(self.init_para)
  self.obj_A.instense()
  print(self.num)
haha = B("this is para")
haha.show()


----------
this is para

init obj A

1

   析构方法:

   __del__:销毁实例时,方法才会执行。

class Hello(object):
    def __del__(self):
        print("你删除了实例")
# 在python上测试
instance = Hello()
del instance
# 当然也可以使用实例调用,但没有这么用的~~
instance.__del__()


  自定义方法:

  除去类中自带的以_下划线开头的函数,在类中定义一个函数,实现相应的功能。

class Person(object):
    def __init__(self,person_name, person_age)

   静态方法:

    @staticmethod,不需要访问类里的任何参数。所带的参数都是从外部传入的。

class Person(object):
    def __init__(self,person_name, person_age):
        self.name = person_name
        self.age = person_age
        
    @staticmethod
    def info(country):
        print(country)

   类方法:

   @classmethod,第一个参数必须是类属性。

class Person(object):
    country = "china"
    def __init__(self,person_name, person_age):
        self.name = person_name
        self.age = person_age
        
    @classmethod
    def info(country):
        print(country)

    属性方法:

    @property把一个函数变成一个静态属性

    直接调用函数名字,不需要加括号,就能获取到函数返回值。一般用在不注重过程,只要结果的情况!

class Person(object):
    country = "china"
    def __init__(self,person_name, person_age):
        self.name = person_name
        self.age = person_age

    @property
    def health_point(self):
        print("HP:【{}】".format(self.age*2))
        return self.age*2

P = Person("laowang",23)
P.health_point                # 不需要括号,看起来完全是一个属性,这就是属性方法

    

    特殊成员方法:

方法
作用示例结果
__call__

默认未定义

类实例化后,调用实例运行的方法

p = Person()

p()

Person是类名

实例p没有调用函数,加()运行call方法

__str__

默认未定义,定义时必须有返回值

定义时,打印实例,输入str返回值

p = Person()

print (p)

Person是类名

打印实例p,运行str方法,打印返回值

__getitem__
用于索引操作,如字典。获取数据

p = Person()

p['name']

自动运行getitem
__setitem__
用于索引操作,如字典。赋值

p = Person()

p['name'] = 'David'

自动运行setitem
__delitem__
用于索引操作,如字典。删除数据

p = Person()

del p['name']

自动运行delitem
__new__

类实例化时,执行__new__,并且会阻止

init运行,可以在new里调用init


p = Person()参照例子二
__len__
待续


__cmp__待续
'''例子一call\str\getitem\setitem\delitem方法'''
class Person(object):
 def __call__(self):
  print("print call")
 
 def __str__(self):
  print("print str:",end='')
  return "1"
  
 def __getitem__(self,key):  
  print("getitem:",key)
  
 def __setitem__(self,key,value):
  print('setitem:',key,value)
 
 def __delitem__(self,key):
  print('delitem:',key)
  
p = Person()
p()
print(p)
print('-----------')
get = p['name']
p['name'] = 'David'
del p['name']
'''例子二:__new__/__init__'''
class Person(object):

 def __init__(self):

  print('this is init!')
  

 def __new__(self):

  print("this is new!")

  self.__init__(self)        # 如果去掉这一行,init不能执行
  
p = Person()


    类的来源和元类:

    http://blog.jobbole.com/21351/中文版详细解答。下面写一个自己理解的简版的。

    首先,类也是对象,可以:

    1)   你可以将它赋值给一个变量

    2)   你可以拷贝它

    3)   你可以为它增加属性

    4)   你可以将它作为函数参数进行传递

    

    类也是是由type()这个函数创建的,type是类的类,类的爹。学名叫元类!

    也许有人会问那为啥type()能查看到数据类型呢?因为数据类型在Python中都是类定义的,这也说明了,为什么数字,字符等等全是对象。


    type格式:

    type(类名,(父类元组),{属性字典},{方法词典})  ,  父类元组可以没有;后面两个典省略时,默认值为None。

'''一言不合就上例子'''
class Person(object):
    country = 'china'

Person = type('Person',('object',),{'country':china})


未完待续。。。

  • 类的继承

  • 类的多态

  • 反射

 

 

Python基础:Python类(真累~)

标签:单词   inf   lin   new   dict   自定义   obb   row   存在   

原文地址:http://blog.51cto.com/yishi/2072182

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!