Python面向对象之类的成员

Python面向对象的编程过程中,我们为类实例化了对象,并通过对象指针来访问类中对应的资源,那么这些资源大体分为三大部分,分别是字段、方法和属性,我们将这三大块统称为类的成员。

一、字段

字段可以分为静态字段、动态字段,下面通过代码展示类中的两种字段

class MyClass:
    # 静态字段,属于类,多个对象共用一个静态字段
    leader = "abuve"

    def __init__(self):
        # 动态字段,属于对象,也可以叫普通的字段,每个对象都会有自己独有的动态字段
        self.name = "kevin"

动态字段在类的实例化过程中很常见,通过self为每个对象封装属于自己特有的数据,但如果类中全部采用动态字段,也会遇到一些不合理的弊端,例如下面代码:

class Company:
    def __init__(self, dept, leader):
        self.company_name = "Center"
        self.dept = dept
        self.leader = leader  

    def ...

if __name__ == "__main__":    
    it_dept = Company("IT", "Abuve")
    hr_dept = Company("HR", "Kevin")

我们通过动态字段方式为对象封装了自己独有的数据,但是这里发现公司名称company_name都为“Center”,不管创建哪个部门的对象,公司名称是不变的,我们知道动态字段存放在对象中,这样每个对象就都包含了一份company_name字段,这无疑增加了程序对内存的开销,因此更合理的方式应该使用静态字段,代码如下:

class Company:
    company_name = "Center"

    def __init__(self, dept, leader):
        self.dept = dept
        self.leader = leader    

    def ...

if __name__ == "__main__":
    it_dept = Company("IT", "Abuve")
    hr_dept = Company("HR", "Kevin")

同时在字段的调用方式上,我们也要遵循一些规则:
1、静态字段,属于类,通过类来调用访问
2、动态字段,属于对象,通过对象来调用访问

对于上述代码,我们通过下面的方式访问其中的字段数据:

print it_dept.deptprint 
hr_dept.leaderprint 
Company.company_name

如果通过对象访问静态字段同样可以访问到数据,因为对象也是通过对象指针指向了自己的类,对象中没有的数据最终也会去类中查找,但是这样的调用方式并不合理。

通过对象调用,同样访问到了类的静态字段

print it_dept.company_name

在字段前加入两个下划线,可以将该字段设置为私有字段,例如:

class MyClass:
    def __init__(self, name):
        self.__name = name 

    def show(self):
        print self.__name

if __name__ == "__main__":
    object = MyClass("Abuve")    # 通过对象无法访问到私有字段
    print object.__name    # 私有字段通过类的内部方法访问
    object.show()    # 通过类名前加入下划线的方式同样可以访问到
    print object._MyClass__name

最后一种方式通过类名前加入下划线的方式同样访问到了私有字段,但多数情况下尽量不要用这种方式进行访问。

二、方法

在Python面向对象编程中,方法的调用最为常见,分为动态方法(普通方法)、静态方法、类方法,下面通过代码展示。

class MyClass:
    def __init__(self, name):
        self.name = name 

    # 普通方法
    def show(self):
        return self.name 

    # 静态方法
    @staticmethod
    def detail(name):
        print '%s is good person.' %name 

    # 动态方法
    @classmethod
    def show_detail(cls):
        cls.detail('Kevin') 

if __name__ == "__main__":
    object = MyClass("Jack")
    p_name = object.show()
    MyClass.detail(p_name)
    MyClass.show_detail()

与字段一样,方法的调用上依然要遵循一些规则。
1、普通方法,由对象调用
2、静态方法,由类调用
3、类方法,属于静态方法的一种,通过类来调用,执行的时候会自动将类名传递进去,因此要有一个默认的接收参数。

静态方法依然也可以通过对象指针来访问到,但是这样调用并不合理,之所以将这种稍微特殊的方法写到类中,也是因为其与该类具备一定的相关性。

三、属性

如果说字段属于左派、方法属于右派,那么属性就属于中立派,因为它即具备方法的功能,同时又可以通过字段的方式来访问,下面为一段包含属性的代码段。

class PageSet:
    def __init__(self, count, page_size):
        self.count = count
        self.page_size = page_size 
# 通过装饰器将page_num变为属性,对象调用时不需要再加括号
  @property
    def page_num(self):
        page_count, remainder  = divmod(self.count, self.page_size)    

        if remainder == 0:
            return page_count
        else:
            return page_count + 1

if __name__ == "__main__":    
# 传入条目总数,以及单页size大小
  page_tools = PageSet(108, 10)    
    # 像访问字段一样执行了page_num方法
    print page_tools.page_num

上面的代码实现了一个分页设置,我们通过装饰器property将page_num方法变为属性,那么该方法在被对象调用时,就像访问字段一样,不需要再加括号了。此时我们只实现了通过字段的方式来访问方法,通过下面的代码,我们也可以为属性调用相关的赋值、删除动作。

class PageSet:
    def __init__(self, count, page_size):
        self.count = count
        self.page_size = page_size 

    @property
    def page_num(self):
        page_count, remainder  = divmod(self.count, self.page_size)        

        if remainder == 0:           
            return page_count       
        else:            
            return page_count + 1

    @page_num.setter
    def page_num(self, value):
        print value        
        print 'This is set function.'

    @page_num.deleter
    def page_num(self):
        print 'This is delete function.'

if __name__ == "__main__":
    page_tools = PageSet(108, 10)    
    # 调用property修饰属性
    page_tools.page_num    
    # 调用page_num.setter修饰属性
    page_tools.page_num = 12
    # 调用page_num.deleter修饰属性
    del page_tools.page_num

四、特殊成员

特殊成员指函数两边都带有下划线的特殊方法,这些特殊方法为类提供独有的功能。

1、init
构造方法,这类方法最为常见,在我们实例化类的时候,就是通过init构造方法封装了对象的数据。

2、 del
析构函数,通过del函数构造特定功能,在为对象执行del操作时,可以自动调用该部分代码,在程序执行相关垃圾回收时,可以应用析构方法。

3、doc
注释,通过对象,可以访问到doc函数中指定的注释内容。

4、module
通过该方法可以显示当前对象属于哪个模块。

5、class
通过该方法可以显示当前对象属于哪个类。

6、call
如果我们在类的实例化对象后面加括号时,会自动执行类中的call方法。

class MyClass:
    def __call__(self):
        print 'This is something...'

 if __name__ == "__main__":
    object = MyClass()
    object()

7、str
默认打印对象时,只能够显示内存地址,通过str可以显示想要返回的内容。

class MyClass:
    def __str__(self):
        return 'This is text that I want to return...'

 if __name__ == "__main__":
    object = MyClass()    
    print object

8、add
可以将两个对象中的内容进行相加。

class MyClass:
    def __init__(self, company, ceo):
        self.company = company
        self.ceo = ceo 

    def __add__(self, other):
        return "%s---%s" %(self.company, other.ceo)

obj1 = MyClass("A","Abuve")
obj2 = MyClass("B", "Kevin")
print obj1 + obj2

代码最终打印了 "A---Kevin"

9、dict
对象调用该方法,可以打印出所有封装的数据,类调用该访问可以打印出所有方法。

10、getitemsetitemdelitem
通过字典的方式操作对象,可以为其设置相应的执行动作。

class MyClass(object):
    def __getitem__(self, key):
        print '__getitem__',key 

    def __setitem__(self, key, value):
        print '__setitem__',key,value 

    def __delitem__(self, key):
        print '__delitem__',key 

if __name__ == "__main__":
    obj = Myclass()      
    result = obj['k1']   # 执行了__getitem__方法
    obj['k2'] = 'abuve'  # 执行了__setitem__方法
    del obj['k1']   # 执行了__delitem__方法

11、iter
用于迭代器,返回一个可以被迭代的对象

class MyClass(object):
    def __iter__(self):
        return iter([1,2,3,4,5]) 

if __name__ == "__main__":
    obj = MyClass()    
    for i in obj:        
        print i

12、isinstance/issubclass
通过isinstance可以判断某个对象的类型,issubclass可以判断某两个类是否为继承关系

class Class1():
    pass
 class Class2(Class1):
    pass
 if __name__ == "__main__":
    obj = Class2()    # 判断obj的类型是否为Class2
    print isinstance(obj, Class2)    # isinstance同样也可以判断是否继承自父类
    print isinstance(obj, Class1)    
    print issubclass(Class2, Class1)

本次分享就到这了,对您有帮助的话,点个关注再走吧~

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

推荐阅读更多精彩内容