面向对象
静态函数,类函数,成员函数,属性函数的区别
补充知识:
- 实例变量:每个实例独有的变量
类变量:所有实例共享的变量
形象理解:哈士奇(类变量)是狗的一种,而每只狗都只会有一个主人给它取唯一的名字,例如“蛤蛤”(成员变量)。用代码来解释就是
1
2
3
4class Dog:
kind = "Husky" # 类变量
def __init__(self, name):
self.name = name # 实例变量四类函数的定义
明确了实例变量和类变量之后,四类函数就很好理解了。先看官方定义:
静态函数(@staticmethod):即静态方法,不可以访问实例变量或类变量。
- 类函数(@classmethod):只能访问类变量,不能访问实例变量。
- 成员函数:实例后使用的方法,且只能通过实例进行调用。
- 属性函数(@property):通过装饰器@property把一个方法变成一个静态属性
四类函数的形象解释
再次请出“蛤蛤”,首先讲解静态函数:通俗的说静态方法就是函数的形参中没有self。也即,静态函数与类中的静态变量&实例变量都没有半毛钱关系1
2
3
4
5
6
7
8
9class Dog(object):
def bark():
print("my name is Haha")
d1 = Dog()
d1.bark()
# 使用静态方法,输出结果为my name is Haha
那么类函数呢?1
2
3
4
5
6
7
8
9
10class Dog(object):
name = "Haha"
def bark(cls):
print("my name is %s" % cls.name)
d2 = Dog()
d2.bark()
# 使用类方法,输出结果为my name is Haha
再看看成员函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class Dog(object):
name = "Haha"
def __init__(self, nick_name):
self.nick_name = nick_name
def bark(self):
print("my name is %s and my nick name is %s" % (name,self.nick_name))
d3 = Dog("Heiha")
d3.bark()
# 使用成员函数,输出结果为my name is Haha and my nick name is Heiha
```
最后看看属性函数:
```py
class Dog(obkect):
def __init__(self, name):
self.name = name
def bark(self):
print("my name is %s" % self.name)
# 使用属性函数的方式需要注意!此时bark函数已经是Dog类的一个属性。
d4 = Dog("Haha")
# 如此使用属性函数,输出结果为myname is Haha
d4.talk
补充:@property的使用
为什么需要有@property装饰器?
编程中出现的问题:绑定属性的时候无法检查参数!
- 解决方案一:在类中定义set()和get()方法来设置与获取成绩。这么写是OK的,但是当你把类进行实例化之后,就会懂得这个方案的麻烦程度了。
@property把方法变成属性调用
使用方法:把你想要设置的属性变成一个getter方法,在加上@property
装饰器,在setter方法里就可以检查参数的合法性了。
实例化之后,就可以直接绑定属性而不用再去调用类方法!
1 | class Student(object): |
四类函数的小总结:
综上所述,其实我们可以四类函数当做一个逐渐释放权力的过程。当使用静态函数时,类的任何信息你都无权得到;当你使用类函数时,你只可以得到类变量里面的信息,而无法得到实例化之后的类的信息;只有当你使用成员函数,你的权力才得到完整的释放,你既可以使用类变量的信息又可以使用实例化后类的信息。而属性函数则是把一个函数当做属性来看待,这是最好理解的。
我还是不懂何时使用它们怎么办?
记住核心思想:
- 类函数主要用途是作为构造函数。
- 静态函数的形参没有self
- 成员函数用的最多
类的访问控制:单下划线_与双下划线__
- “_”:单下划线表示只允许其本身与其子类进行访问
- “__”:双下划线表示只允许这个类本身进行访问。
python语言特性
python是动态类型语言
在编写代码的时候可以不指定变量的数据类型
with语句:
1 | # 1. with语句的语法格式 |
错误处理
- 一个简单易懂的例子:如果某些代码可能会出错
1
2
3
4
5
6
7
8try:
r = 10 / 0
except ZeroDivisonError, e:
print "ZeroDivisionError", e
except ValueError, e:
print "ValueError", e
finally:
print 'finally' 记录错误:打印错误信息,同时让程序继续执行
1
2
3
4
5
6
7
8
9
10import logging
def foo(s):
return 10 / int(s)
def main():
try:
foo('0')
except StandardError, e:
logging.exception(e)
main()
print "END"程序打印完错误信息后会继续执行,并且正常退出。
抛出错误
1
2
3
4try:
10 / 0
except ZeroDivisionError:
raise ValueError('input error!')
代码trick
再见!中间变量
1 | a = 1 |
字符串逆序
实质是把字符串转换成列表进行操作1
2
3
4
5a = "python"
# 方法一:看起来很装逼的方法
print a[::-1] # "nohtyp"
# 方法二:可读性强的方法
print list(a).reverse()
python可以使用连续赋值, 从左至右
1 | x = [0, 1] |
矩阵转置
其原理为zip()函数:将对象中对应的元素打包成一个个元组,并且返回由元组组成的列表。这恰好符合矩阵转置的操作1
2
3
4mat = [[1, 2, 3], [4, 5, 6]]
# *可以简单理解为解压
print zip(*mat)
#[(1, 4), (2, 5), (3, 6)]
列表转字符串
1 | a = ["Code", "mentor", "Python", "Developer"] |
在一个for循环中遍历两个列表
1 | list1 = ['a','b','c','d'] |
同时处理多个文件
1 | with open(filename1) as fp1, open(filename2) as fp2, open(filename3) as fp3: |
给字符串前面补“0”
1 | num = "123" |
回调函数 callback()
官方解释:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
形象解释:
吃饭、喝水、睡觉就是一个通过大脑调用的动作。如果你把这些动作作为参数传递给大脑,当这些动作被用来真正去执行时,我们就说这是回调函数。
代码解释:
1 | def eat(food): |
测试文件
1 | from foo import * |
参考与引用
- https://m.baidu.com/?from=844b&vit=fps&nsukey=QL%2FYJKapoliD84rv4ROf08qlZJ83uWDoXzrVj
- https://www.cnblogs.com/scf141592/p/5726347.html
- https://www.cnblogs.com/crazyrunning/p/6945183.html
- https://www.cnblogs.com/polly333/p/8143672.html
- https://www.cnblogs.com/crazyrunning/p/6945183.html
- https://www.cnblogs.com/imageSet/p/7473326.html
- https://www.jianshu.com/p/4bd8a1c93cbe
- https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386820062641f3bcc60a4b164f8d91df476445697b9e000
- https://www.liaoxuefeng.com/
- https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/
- https://www.cnblogs.com/alamZ/p/6943869.html