Skip to content

Commit bbbfa64

Browse files
committed
Signed-off-by: twowater <[email protected]>
草根学Python(九) 面向对象
1 parent 278330d commit bbbfa64

File tree

9 files changed

+577
-2
lines changed

9 files changed

+577
-2
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
|草根学Python(五) 条件语句和循环语句|[掘金](https://juejin.im/post/594c6c52f265da6c1f75f164)[简书](http://www.jianshu.com/p/2b80009b1e8c)[CSDN](http://blog.csdn.net/Two_Water/article/details/73762517)[个人博客](http://twowater.com.cn/2017/06/27/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E4%BA%94-%E6%9D%A1%E4%BB%B6%E8%AF%AD%E5%8F%A5%E5%92%8C%E5%BE%AA%E7%8E%AF%E8%AF%AD%E5%8F%A5/)|
1616
|草根学Python(六) 函数|[掘金](https://juejin.im/post/5946784461ff4b006cf1d8ec)[简书](http://www.jianshu.com/p/d8f2a55edc75)[CSDN](http://blog.csdn.net/Two_Water/article/details/73865622)[个人博客](http://twowater.com.cn/2017/06/29/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E5%85%AD-%E5%87%BD%E6%95%B0/)|
1717
|草根学Python(七) 迭代器和生成器|[掘金](https://juejin.im/post/59589fedf265da6c386ce4ac)[简书](http://www.jianshu.com/p/74c0c1db1490)[CSDN](http://blog.csdn.net/Two_Water/article/details/74164652)[个人博客](http://twowater.com.cn/2017/07/02/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E4%B8%83-%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E7%94%9F%E6%88%90%E5%99%A8/)|
18-
|草根学Python(八) 模块与包|[掘金](https://juejin.im/post/5962ddf95188252ec34009da)[简书](http://www.jianshu.com/p/7f05f915d2ac)[CSDN](http://blog.csdn.net/Two_Water/article/details/75042211)[个人博客](http://twowater.com.cn/2017/07/12/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E5%85%AB-%E6%A8%A1%E5%9D%97%E4%B8%8E%E5%8C%85/)|
18+
|草根学Python(八) 模块与包|[掘金](https://juejin.im/post/5962ddf95188252ec34009da)[简书](http://www.jianshu.com/p/7f05f915d2ac)[CSDN](http://blog.csdn.net/Two_Water/article/details/75042211)[个人博客](http://twowater.com.cn/2017/07/12/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E5%85%AB-%E6%A8%A1%E5%9D%97%E4%B8%8E%E5%8C%85/)|
19+
|草根学Python(九) 面向对象|[掘金](https://juejin.im/post/596ca6656fb9a06b9b73c8b0)[简书](http://www.jianshu.com/p/6ecaa414c702)[CSDN](http://blog.csdn.net/two_water/article/details/76408890)[个人博客](http://twowater.com.cn/2017/07/31/%E8%8D%89%E6%A0%B9%E5%AD%A6Python-%E4%B9%9D-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/)|

SUMMARY.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,11 @@
4242
- [模块的使用](/python8/2.md)
4343
- [主模块和非主模块](/python8/3.md)
4444
- [](/python8/4.md)
45-
- [作用域](/python8/5.md)
45+
- [作用域](/python8/5.md)
46+
* [面向对象](/python9/Preface.md)
47+
- [面向对象的概念](/python9/1.md)
48+
- [](/python9/2.md)
49+
- [类的属性](/python9/3.md)
50+
- [类的方法](/python9/4.md)
51+
- [类的继承](/python9/5.md)
52+
- [类的多态](/python9/6.md)

python9/1.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# 一、面向对象的概念 #
2+
3+
Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 用 JAVA 的编程思想来说就是:万事万物皆对象。也就是说在面向对象中,把构成问题事务分解成各个对象。
4+
5+
面向对象有三大特性,封装、继承和多态。
6+
7+
## 1、面向对象的两个基本概念 ##
8+
9+
* ****
10+
11+
用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
12+
13+
* **对象**
14+
15+
通过类定义的数据结构实例
16+
17+
18+
## 2、面向对象的三大特性 ##
19+
20+
* **继承**
21+
22+
即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
23+
24+
例如:一个 Dog 类型的对象派生自 Animal 类,这是模拟"是一个(is-a)"关系(例图,Dog 是一个 Animal )。
25+
26+
* **多态**
27+
28+
它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
29+
30+
* **封装性**
31+
32+
“封装”就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体(即类);封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。

python9/2.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# 二、类 #
2+
3+
## 1、定义类 ##
4+
5+
类定义语法格式如下:
6+
7+
```python
8+
class ClassName:
9+
<statement-1>
10+
.
11+
.
12+
.
13+
<statement-N>
14+
```
15+
16+
一个类也是由属性和方法组成的,有些时候我们定义类的时候需要设置类的属性,因此这就需要构造函
17+
18+
类的构造函数如下:
19+
20+
```python
21+
def __init__(self,[...):
22+
```
23+
24+
类定义了 __init__() 方法的话,类的实例化操作会自动调用 __init__() 方法。
25+
26+
那么如构造函数相对应的是析构函数,理所当然,一个类创建的时候我们可以用过构造函数设置属性,那么当一个类销毁的时候,就会调用析构函数。
27+
28+
析构函数语法如下:
29+
30+
```python
31+
def __del__(self,[...):
32+
```
33+
34+
仔细观察的童鞋都会发现,类的方法与普通的函数有一个特别的区别,它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
35+
36+
那么这个 self 代表什么呢?
37+
38+
我们可以看下实例,通过实例来找出答案:
39+
40+
```python
41+
#!/usr/bin/env python3
42+
# -*- coding: UTF-8 -*-
43+
44+
class Test:
45+
def prt(self):
46+
print(self)
47+
print(self.__class__)
48+
49+
t = Test()
50+
t.prt()
51+
```
52+
53+
观察输出的结果:
54+
55+
![Python self](https://user-gold-cdn.xitu.io/2017/7/30/933b74a7ae0e312c40806ea8dad092d4)
56+
57+
从执行结果可以很明显的看出,self 代表的是类的实例,输出的是当前对象的地址,而 `self.__class__` 则指向类。
58+
59+
当然 self 不是 python 关键字,也就是说我们把他换成其他的字符也是可以正常执行的。只不过我们习惯使用 self
60+
61+
## 2、Python 定义类的历史遗留问题 ##
62+
63+
Python 在版本的迭代中,有一个关于类的历史遗留问题,就是新式类和旧式类的问题,具体先看以下的代码:
64+
65+
```python
66+
#!/usr/bin/env python
67+
# -*- coding: UTF-8 -*-
68+
69+
# 旧式类
70+
class OldClass:
71+
pass
72+
73+
# 新式类
74+
class NewClass(object):
75+
pass
76+
77+
```
78+
79+
可以看到,这里使用了两者中不同的方式定义类,可以看到最大的不同就是,新式类继承了`object` 类,在 Python2 中,我们定义类的时候最好定义新式类,当然在 Python3 中不存在这个问题了,因为 Python3 中所有类都是新式类。
80+
81+
那么新式类和旧式类有什么区别呢?
82+
83+
运行下下面的那段代码:
84+
85+
```python
86+
#!/usr/bin/env python
87+
# -*- coding: UTF-8 -*-
88+
89+
# 旧式类
90+
class OldClass:
91+
def __init__(self, account, name):
92+
self.account = account;
93+
self.name = name;
94+
95+
96+
# 新式类
97+
class NewClass(object):
98+
def __init__(self, account, name):
99+
self.account = account;
100+
self.name = name;
101+
102+
103+
if __name__ == '__main__':
104+
old_class = OldClass(111111, 'OldClass')
105+
print(old_class)
106+
print(type(old_class))
107+
print(dir(old_class))
108+
print('\n')
109+
new_class=NewClass(222222,'NewClass')
110+
print(new_class)
111+
print(type(new_class))
112+
print(dir(new_class))
113+
114+
```
115+
116+
117+
仔细观察输出的结果,对比一下,就能观察出来,注意喔,Pyhton3 中输出的结果是一模一样的,因为Python3 中没有新式类旧式类的问题。
118+

python9/3.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 三、类的属性 #
2+
3+
## 1、直接在类中定义属性 ##
4+
5+
定义类的属性,当然最简单最直接的就是在类中定义,例如:
6+
7+
```python
8+
class UserInfo(object):
9+
name='两点水'
10+
```
11+
12+
## 2、在构造函数中定义属性 ##
13+
14+
故名思议,就是在构造对象的时候,对属性进行定义。
15+
16+
```python
17+
class UserInfo(object):
18+
def __init__(self,name):
19+
self.name=name
20+
```
21+
22+
## 3、属性的访问控制 ##
23+
24+
在 Java 中,有 public (公共)属性 和 private (私有)属性,这可以对属性进行访问控制。那么在 Python 中有没有属性的访问控制呢?
25+
26+
一般情况下,我们会使用 `__private_attrs` 两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 `self.__private_attrs`
27+
28+
为什么只能说一般情况下呢?因为实际上, Python 中是没有提供私有属性等功能的。但是 Python 对属性的访问控制是靠程序员自觉的。为什么这么说呢?看看下面的示例:
29+
30+
![Python 属性访问控制](https://user-gold-cdn.xitu.io/2017/7/28/cf3ef904a9c84bd15245cd1f0e1f3e88)
31+
32+
仔细看图片,为什么说双下划线不是真正的私有属性呢?我们看下下面的例子,用下面的例子来验证:
33+
34+
```python
35+
36+
#!/usr/bin/env python
37+
# -*- coding: UTF-8 -*-
38+
39+
class UserInfo(object):
40+
def __init__(self, name, age, account):
41+
self.name = name
42+
self._age = age
43+
self.__account = account
44+
45+
def get_account(self):
46+
return self.__account
47+
48+
49+
if __name__ == '__main__':
50+
userInfo = UserInfo('两点水', 23, 347073565);
51+
# 打印所有属性
52+
print(dir(userInfo))
53+
# 打印构造函数中的属性
54+
print(userInfo.__dict__)
55+
print(userInfo.get_account())
56+
# 用于验证双下划线是否是真正的私有属性
57+
print(userInfo._UserInfo__account)
58+
59+
60+
```
61+
62+
输出的结果如下图:
63+
64+
![Python 属性访问控制](https://user-gold-cdn.xitu.io/2017/7/28/b147b0390a9b4cbcd5765658b54c12e9)

python9/4.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# 四、类的方法 #
2+
3+
## 1、类专有的方法 ##
4+
5+
一个类创建的时候,就会包含一些方法,主要有以下方法:
6+
7+
类的专有方法:
8+
9+
| 方法 | 说明 |
10+
| ------| ------ |
11+
|`__init__` |构造函数,在生成对象时调用|
12+
|`__del__ `| 析构函数,释放对象时使用|
13+
|`__repr__ `| 打印,转换|
14+
|`__setitem__ `| 按照索引赋值|
15+
|`__getitem__`| 按照索引获取值|
16+
|`__len__`| 获得长度|
17+
|`__cmp__`| 比较运算|
18+
|`__call__`| 函数调用|
19+
|`__add__`| 加运算|
20+
|`__sub__`| 减运算|
21+
|`__mul__`|乘运算|
22+
|`__div__`| 除运算|
23+
|`__mod__`| 求余运算|
24+
|`__pow__`|乘方|
25+
26+
当然有些时候我们需要获取类的相关信息,我们可以使用如下的方法:
27+
28+
* `type(obj)`:来获取对象的相应类型;
29+
* `isinstance(obj, type)`:判断对象是否为指定的 type 类型的实例;
30+
* `hasattr(obj, attr)`:判断对象是否具有指定属性/方法;
31+
* `getattr(obj, attr[, default])` 获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;
32+
* `setattr(obj, attr, value)`:设定该属性/方法的值,类似于 obj.attr=value;
33+
* `dir(obj)`:可以获取相应对象的所有属性和方法名的列表:
34+
35+
## 2、方法的访问控制 ##
36+
37+
其实我们也可以把方法看成是类的属性的,那么方法的访问控制也是跟属性是一样的,也是没有实质上的私有方法。一切都是靠程序员自觉遵守 Python 的编程规范。
38+
39+
示例如下,具体规则也是跟属性一样的,
40+
41+
```python
42+
#!/usr/bin/env python
43+
# -*- coding: UTF-8 -*-
44+
45+
class User(object):
46+
def upgrade(self):
47+
pass
48+
49+
def _buy_equipment(self):
50+
pass
51+
52+
def __pk(self):
53+
pass
54+
55+
```
56+
57+
## 3、方法的装饰器 ##
58+
59+
60+
* **@classmethod**
61+
调用的时候直接使用类名类调用,而不是某个对象
62+
63+
* **@property**
64+
可以像访问属性一样调用方法
65+
66+
具体的使用看下实例:
67+
68+
```python
69+
#!/usr/bin/env python
70+
# -*- coding: UTF-8 -*-
71+
72+
class UserInfo(object):
73+
lv = 5
74+
75+
def __init__(self, name, age, account):
76+
self.name = name
77+
self._age = age
78+
self.__account = account
79+
80+
def get_account(self):
81+
return self.__account
82+
83+
@classmethod
84+
def get_name(cls):
85+
return cls.lv
86+
87+
@property
88+
def get_age(self):
89+
return self._age
90+
91+
92+
if __name__ == '__main__':
93+
userInfo = UserInfo('两点水', 23, 347073565);
94+
# 打印所有属性
95+
print(dir(userInfo))
96+
# 打印构造函数中的属性
97+
print(userInfo.__dict__)
98+
# 直接使用类名类调用,而不是某个对象
99+
print(UserInfo.lv)
100+
# 像访问属性一样调用方法(注意看get_age是没有括号的)
101+
print(userInfo.get_age)
102+
```
103+
104+
运行的结果:
105+
106+
![Python 方法的装饰器](https://user-gold-cdn.xitu.io/2017/7/29/94ae6aec01a94136951cbb8314008781)

0 commit comments

Comments
 (0)