三大成员

  在Python的面向对象中,主要包括三大成员:字段、方法、属性

字段

  类成员的字段又可分为普通字段、静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,代码示例如下:

  1. class Foo:
  2. #字段:静态字段
  3. CC = 123
  4. def __init__(self, name):
  5. # 字段:普通字段
  6. self.name = name
    访问普通字段:
    obj = Foo('bob')
    print(obj.name)
    out: bob
  7.  
  8. 访问静态字段:
    print(Foo.CC)
    out: 123

1.普通字段:self.xxx

  从上边的例子可以看出,普通字段存储在对象中,需要通过对象去访问。

2.静态字段:

  从上边的例子可以看出,静态字段写在方法外边,只属于类,保存在类里边,不需要实例化也能访问,可以直接通过类去访问。可以起到节省内存的作用,静态字段代码加载的时候已经在内存创建。当然了,也可以通过对象去访问,但是不推荐

小结:

  普通字段只能用对象访问。静态字段用类访问(不建议用对象访问).且静态字段未做修改之前,对象共享一块内存地址。当对静态字段进行修改后,对象拥有自己的静态字段,不再共享

方法

  方法分为普通方法、静态方法和类方法。这三种方法在内存中都归属于类。代码如下:

  1. class Foo:
  2. # 字段:静态字段
  3. CC = 123
  4.  
  5. def __init__(self, name):
  6. # 字段:普通字段
  7. self.name = name
  8.  
  9. # 普通方法
  10. def show(self):
  11. print(self.name)
  12.  
  13. # 静态方法
    @staticmethod
  14. def f1(arg):
  15. print("静态方法" + arg)
  16.  
  17. # 类方法
  18. @classmethod
  19. def f2(cls):
  20. print("类方法")
  21. print(cls)
    # 调用普通方法:
    obj = Foo('bob')
    obj.show()
    out: bob
    # 调用静态方法;
    Foo.f1('Bob')
    out: 静态方法bob
    # 调用类方法:
    Foo.f2()
    out: 类方法 <class '__main__.Foo'>

1. 普通方法:由对象调用

  至少包含一个self参数,并且在执行普通方法时,自动将调用该方法的对象赋值给self

2. 静态方法:由类调用

  由staticmethod装饰,且无默认参数self,可以根据对应方法,接收任意参数。当方法内部不需要对象中封装的值时,可以将方法写成静态方法。

3. 类方法:由类调用

  类方法是静态方法的特殊形式,至少一个包含cls参数;该参数不需要传递,会自动进行传递,执行类方法时,自动将调用该方法的类名赋值给cls。

小结:

  相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同。

属性

  属性其实就是类中普通方法的变种。属性具有方法的写作形式,具有字段的访问方式,并且提供了一种关联方式。定义方法如下

定义方式1:对方法使用装饰器

  1. class Pager:
  2. CC = 123
  3. def __init__(self, all_count):
  4. self.all_count = all_count
  5.  
  6. @property
  7. def all_pager(self):
  8. a1, a2 = divmod(self.all_count, 10)
  9. if a2 == 0:
  10. return a1
  11. else:
  12. return a1 + 1
  13.  
  14. @all_pager.setter
  15. def all_pager(self, value):
  16. self.all_count = value
  17. print(self.all_count)
  18.  
  19. @all_pager.deleter
  20. def all_pager(self):
  21. print('del ' , Pager.CC)

  22. # 自动执行@property修饰的all_pager方法
  23. obj = Pager(101)
  24. print(obj.all_pager)
  25. out: 11

  26. # 自动执行@all_pager.setter修饰的all_pager方法
  27. obj.all_pager = 99
  28. out: 99
  29.  
  30. print(obj.all_pager)
  31. out: 10

  32. # 自动执行@all_pager.deleter修饰的all_pager方法
  33. del obj.all_pager
  34. out: del 123

定义方式2:创建property对象

  1. class Pager:
  2. def __init__(self, all_count):
  3. self.all_count = all_count
  4.  
  5. def f1(self):
  6. return 123
  7.  
  8. def f2(self, value):
  9. print('执行f2 ' + value)
  10.  
  11. def f3(self):
  12. print("执行f3")
  13.  
  14. foo = property(fget=f1,fset=f2,fdel=f3)
  15.  
  16. p = Pager(101)
  17.  
  18. # 执行f1方法
  19. result = p.foo
  20. print(result) # out: 123
  21.  
  22. # 执行f2方法
  23. p.foo = 'xxxxx' # out: 执行f2 xxxxx
  24.  
  25. # 执行f3方法
  26. del p.foo # out: 执行f3

类成员修饰符

  类成员修饰符,顾名思义,就是用来修饰字段、方法和属性的。对于每一个类的成员,都有两种形式:共有成员和私有成员。

私有成员和公有成员的定义不同

  私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)

私有成员和公有成员的访问限制不同

静态字段

公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问;

  1. class C:
  2. name = "公有静态字段"
  3. def func(self):
  4. print(C.name)
  5.  
  6. class D(C):
  7. def show(self):
  8. print(C.name)
  9.  
  10. print(C.name) # 类访问
  11. out 公有静态字段
  12. obj = C()
  13. obj.func() # 类内部可以访问
  14. out 公有静态字段
  15. obj_son = D()
  16. obj_son.show() # 派生类中可以访问
  17. out 公有静态字段

公有静态字段

  1. class C:
  2. __name = "公有静态字段"
  3. def func(self):
  4. print(C.__name)
  5.  
  6. class D(C):
  7. def show(self):
  8. print(C.__name)
  9.  
  10. print(C.__name) # 类访问 ==> 错误
  11. out: AttributeError: type object 'C' has no attribute '__name'
  12. # obj = C()
  13. obj.func() # 类内部可以访问 ==> 正确
  14. # out: 公有静态字段
  15. obj_son = D()
  16. obj_son.show() # 派生类中可以访问 ==> 错误
  17. # out: AttributeError: type object 'C' has no attribute '_D__name'

私有静态字段

普通字段

公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
私有普通字段:仅类内部可以访问;代码同静态字段的测试方法是一样,这里不再距离。

ps:非要访问私有属性的话,可以通过 "对象._类名__属性名"的方式来访问。代码如下:

  1. class C:
  2. __name = "公有静态字段"
  3. def func(self):
  4. print(C.__name)
  5.  
  6. class D(C):
  7. def show(self):
  8. print(C.__name)
  9.  
  10. obj = D()
  11. print(obj._C__name)
  12. out: 公有静态字段

强制访问私有字段

类特殊成员

  常用的类特殊成员如下

1. __init__  构造方法,类在实例化的时候自动执行
2. __doc__ 表示类的描述信息
3. __module__ 表示当前操作的对象在哪个模块
4. __class__    表示当前操作的对象的类是什么
5. __call__ 对象后面加括号,触发执行__call__方法。比如A=Foo(), A()会自动出发__call__方法。
6. __str__ 该方法return什么,print(obj)的时候自动调用该方法,否则返回对象地址。或者执行str() ,自动调用该方法
7. __del__ 析构方法,一般不需要自己实现。在类在被垃圾回收机制清理之前, 会自动执行该方法。
8. __add__ 一个对象加另外一个对象,就自动执行 ret = obj1 +obj2. 知道就行,很少用到
9. __dict__ 不用写,默认已经有一个dict。 obj.__dict__ . 获取对象中封装的数据

10. __setitem__, __getitem__, __delitem__

方式一:输入类型为str

  1. class Foo(object):
  2. def __init__(self,name,age):
  3. self.name = name
  4. self.age = age
  5.  
  6. def __getitem__(self, key):
  7. print('__getitem__',key)
  8.  
  9. def __setitem__(self, key, value):
  10. print('__setitem__',key,value)
  11. # print(value[key])
  12.  
  13. def __delitem__(self, key):
  14. print('__delitem__',key)
  15.  
  16. obj = Foo('Boss', 18)
  17. # 执行obj['...']的时候执行__getitem__
  18. obj['Baby']
  19. out: __getitem__ Baby
  20.  
  21. # 执行obj['...'] = ...的时候执行__setitem__
  22. obj['Baby'] = 1123
  23. out: __setitem__ Baby 1123
  24.  
  25. # 执行del obj['...']的时候执行__delitem__
  26. del obj['XXOO']
  27. out: __delitem__ XXOO

str:__getitem__、__setitem__、__delitem__

方式二:输入类型为slice,此时key具有三个字段为[start:stop:step],测试代码如下

  1. class Foo(object):
  2. def __init__(self,name,age):
  3. self.name = name
  4. self.age = age
  5.  
  6. def __getitem__(self, key):
  7. print(type(key)) # 类型有两种: str或者 slice
  8. # 如果是输入类型是slice
  9. # print(key.start)
  10. # print(key.stop)
  11. # print(key.step)
  12. # key.step
  13. print('__getitem__',key)
  14.  
  15. def __setitem__(self, key, value):
  16. print('__setitem__',key,value)
  17. print(value[key])
  18.  
  19. def __delitem__(self, key):
  20. print(type(key), key)
  21. # print(key.start)
  22. # print(key.stop)
  23. # print(key.step)
  24. print('__delitem__',key)
  25.  
  26. # obj[key] 自动调用__getitem__
  27. obj = Foo('alex', 18)
  28. obj[1:4:2]
  29. out:
  30. <class 'slice'>
  31. __getitem__ slice(1, 4, 2)
  32.  
  33. # obj[key] = ... 自动调用__setitem__
  34. obj[1:4] = [1,2,3,4,5,6,7]
  35. out:
  36. __setitem__ slice(1, 4, None) [1, 2, 3, 4, 5, 6, 7]
  37. [2, 3, 4]
  38.  
  39. # del obj[key] 自动调用__delitem__
  40. del obj[1:4:2]
  41. out:
  42. <class 'slice'> slice(1, 4, 2)
  43. __delitem__ slice(1, 4, 2)

slice:__getitem__、__setitem__、__delitem__

11.__iter__  对象通常不能被迭代,因此此方法可以使对象可迭代,该方法返回可迭代对象

  1. class Foo(object):
  2. def __iter__(self):
  3. # return iter([11,22,33,44,55])
  4. yield 1
  5. yield 2
  6.  
  7. obj = Foo()
  8. for item in obj:
  9. print(item)
  10.  
  11. out:
  12. 1
  13. 2

__iter__

面向对象的其他知识点

1. isinstance(a, b) 查看a是不是b的实例,或者是b的父类的实例。

2. issubclass(a, b) 查看a是否b的子类

3. 应用:利用类的继承关系,实现有序字典的类

  1. class MyDict(dict):
  2.  
  3. def __init__(self):
  4. # 执行父类的init方法
  5. super(MyDict, self).__init__()
  6. self.li = []
  7.  
  8. def __setitem__(self, key, value):
  9. self.li.append(key)
  10. super(MyDict, self).__setitem__(key, value)
  11.  
  12. def __getitem__(self, item):
  13. pass
  14.  
  15. def __str__(self):
  16. temp_list = []
  17. for key in self.li:
  18. value = self.get(key)
  19. temp_list.append("'%s':%s" % (key, value))
  20. return '{' + ",".join(temp_list) + '}'
  21.  
  22. obj = MyDict()
  23. obj['k1'] = 123
  24. obj['k2'] = 456
  25. print(obj)
  26. out: {'k1':123,'k2':456}

自定义实现简单有序dict

4. 如何执行父类的方法

  1. class C1:
  2. def f1(self):
  3. print('C1.f1')
  4.  
  5. class C2(C1):
  6. def f1(self):
  7. # 主动去执行父类的F1方法
  8. super(C2, self).f1()
  9. print('C2.f1')
  10.  
  11. obj = C2()
  12. obj.f1()
  13. out:
  14. C1.f1
  15. C2.f1

执行父类:super的用法

5. python2中的继承(待补)

其他

设计模式之单例模式

  单例模式可以用类方法或者静态方法来实现

案例:假设有个连接池,用户如果首次去连接,则创建一个池对象,返回给用户或者线程。如果在用户或线程连接的时候,该池对象已经存在,那么则直接返回。当然,也可以定义一个计数器,计算当前已分配地址池和总地址池的关系。代码如下:

  1. class Foo:
  2. instance = None
  3.  
  4. def __init__(self,name):
  5. self.name = name
  6.  
  7. @classmethod
  8. def get_instance(cls, name):
  9. if cls.instance:
  10. return cls.instance
  11. else:
  12. obj = cls(name)
  13. cls.instance = obj
  14. return obj
  15.  
  16. obj1 = Foo.get_instance('alex')
  17. print(obj1)
  18. obj2 = Foo.get_instance('bbb')
  19. print(obj2)
  20. out:
  21. <__main__.Foo object at 0x0000000000B246A0>
  22. <__main__.Foo object at 0x0000000000B246A0>
  23. # 返回相同的地址,说明他们共用一个池对象

单例模式

异常处理

  所以异常处理,就是在可预知或者不可预知的情况下,提前捕捉异常,甚至针对异常进行的一种或一类操作。这里就用到了try语句。try语句的完整语法如下:

  1. try:
  2. # 捕捉这段代码的异常情况
  3. ...
  4. except:
  5. # 检测到异常的处理手段
  6. ...
  7. else:
  8. # 如果未检测到异常的处理手段
  9. ...
  10. finally:
  11. # 无论是否检测到异常,都执行该代码块
  12. ...

  案例就不作过多说明了,这里说另外一个东西,触发异常和自定义异常

触发异常和自定义异常

  python允许程序员自定义异常,用于描述python中没有涉及的异常情况,自定义异常必须继承Exception类,自定义异常按照命名规范以"Error"结尾,显式地告诉程序员这是异常。自定义异常使用raise语句引发,而且只能通过人工方式触发。当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。

  1. # 触发自定义异常
  2. class InputError(Exception):
  3. def __init__(self):
  4. print("输入类型错误")
  5.  
  6. inp = input('请输入一个数字:').strip()
  7. if inp.isdigit():
  8. raise InputError
  9. else:
  10. print(123)
  11.  
  12. 如果输入123
  13. 则会报错。
  14. 测试如下:
  15. 请输入一个数字:123
  16. 输入类型错误
  17. Traceback (most recent call last):
  18. File "E:/学习经历/python勃起/s2.py", line 90, in <module>
  19. raise InputError
  20. __main__.InputError

  

  1. # 捕获自定义异常
    class InputError(Exception):
  1.  
  1.  

  

断言 assert

  assert语句用于检测某个条件表达式是否为真,如果检测到是假,则触发AssertionError

  1. ip = '127.0.1.1'
  2. assert ip == '127.0.0.1'
  3.  
  4. out:
  5. Traceback (most recent call last):
  6. File "E:/学习经历/s2.py", line 109, in <module>
  7. assert ip == '127.0.0.1'
  8. AssertionError

  如果要为assert增加异常说明信息,语法:assert Expression [, message]

  1. ip = '127.0.1.1'
  2. assert ip == '127.0.0.1', 'No network connect, please the network connect again!'
  3. out:
  4. Traceback (most recent call last):
  5. File "E:/学习经历/python勃起/s2.py", line 109, in <module>
  6. assert ip == '127.0.0.1', 'No network connect, please the network connect again!'
  7. AssertionError: No network connect, please the network connect again!

  

Python菜鸟之路:Python基础-类(2)——成员、成员修饰符、异常及其他的更多相关文章

  1. Python菜鸟之路:Django 路由补充1:FBV和CBV - 补充2:url默认参数

    一.FBV和CBV 在Python菜鸟之路:Django 路由.模板.Model(ORM)一节中,已经介绍了几种路由的写法及对应关系,那种写法可以称之为FBV: function base view ...

  2. python学习之路-day2-pyth基础2

    一.        模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...

  3. python基础(27):类成员的修饰符、类的特殊成员

    1. 类成员的修饰符 类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的定义不同:私 ...

  4. java中的类修饰符、成员变量修饰符、方法修饰符。

    类修饰符: public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类. abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. fin ...

  5. VS开发入门三:c#的类的修饰符和成员的修饰符

    初学者经常会犯下的错误就是,修饰符一大堆,而且类和其成员很多修饰符是一样的容易混用 这里总结下 C#修饰符之类修饰符(个 助记 PIPA SS ):public.internal. partial(多 ...

  6. java成神之——ImmutableClass,null检查,字符编码,defaultLogger,可变参数,JavaScriptEngine,2D图,类单例,克隆,修饰符基本操作

    ImmutableClass null检查 字符编码 default logger 函数可变参数 Nashorn JavaScript engine 执行脚本文件 改变js文件输出流 全局变量 2D图 ...

  7. Python学习之路-Day2-Python基础2

    Python学习之路第二天 学习内容: 1.模块初识 2.pyc是什么 3.python数据类型 4.数据运算 5.bytes/str之别 6.列表 7.元组 8.字典 9.字符串常用操作 1.模块初 ...

  8. python学习之路-day1-python基础1

    本节内容: Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else ...

  9. Python学习之路-Day1-Python基础

    学习python的过程: 在茫茫的编程语言中我选择了python,因为感觉python很强大,能用到很多领域.我自己也学过一些编程语言,比如:C,java,php,html,css等.但是我感觉自己都 ...

随机推荐

  1. ELKStack日志离线系统

    通过Filebeat抽取数据到logstash中,转存到ElasticSearch中,最后通过Kibana进行展示 https://www.ibm.com/developerworks/cn/open ...

  2. 使navicat可以通过SSH连接MySQL数据库

    1.编辑/etc/ssh/sshd_config,在最下面添加如下语句 KexAlgorithms diffie-hellman-group1-sha1,curve25519-sha256@libss ...

  3. block传值以及利用block封装一个网络请求类

    1.block在俩个UIViewController间传值 近期刚学了几招block 的高级使用方法,事实上就是利用block语法在俩个UIViewController之间传值,在这里分享给刚開始学习 ...

  4. 飘逸的python - 实现一个pretty函数美丽的输出嵌套字典

    演示样例: d = { "root": { "folder2": { "item2": None, "item1": N ...

  5. vscode - 使用Settings进行同步扩展以及配置信息等

    1. 创建token(记住要复制上面的token): https://github.com/settings/tokens. 2. 创建gist id https://gist.github.com/ ...

  6. badblocks检测磁盘坏道

    1.检测整个盘如/dev/sdb #badblocks -v /dev/sdb > badsectors.txt 2.检测一个分区#badblocks -v /dev/sdb1 > bad ...

  7. JavaScript实现深拷贝(深复制) 面试题

    1.两种方法实现深拷贝(深复制) (1)方法一:兼容性好,请仔细看代码(网上大部分代码有Bug) (2)方法二:需要对象满足JSON数据格式.JOSN数据格式:http://www.cnblogs.c ...

  8. BZOJ 4216 Pig 分块乱搞

    题意:id=4216">链接 方法:分块以节约空间. 解析: 这题坑的地方就是他仅仅有3M的内存限制,假设我们开longlong前缀和是必死的. 所以考虑缩小这个long long数组 ...

  9. windows下WMI使用C++查询用户硬件信息

    最近需要做下用户信息统计,发现WMI真是个好东西,同时觉得COM这东西,还真不能少>_<!! 下面是源码: /*************************************** ...

  10. 关于 Nginx 并发连接数

    关于 Nginx 并发连接数 最近在学习使用 nginx , 做一些简单的压力测试时,发现并发连接数最大只能上到 100 多 测试刚开始时的状态 , netstat -n | awk '/^tcp/ ...