Python语言学习

面向对象

静态函数,类函数,成员函数,属性函数的区别

补充知识:

  • 实例变量:每个实例独有的变量
  • 类变量:所有实例共享的变量

    形象理解:哈士奇(类变量)是狗的一种,而每只狗都只会有一个主人给它取唯一的名字,例如“蛤蛤”(成员变量)。用代码来解释就是

    1
    2
    3
    4
    class Dog:
    kind = "Husky" # 类变量
    def __init__(self, name):
    self.name = name # 实例变量

    四类函数的定义

    明确了实例变量和类变量之后,四类函数就很好理解了。先看官方定义:

  • 静态函数(@staticmethod):即静态方法,不可以访问实例变量或类变量。

  • 类函数(@classmethod):只能访问类变量,不能访问实例变量。
  • 成员函数:实例后使用的方法,且只能通过实例进行调用。
  • 属性函数(@property):通过装饰器@property把一个方法变成一个静态属性

四类函数的形象解释

再次请出“蛤蛤”,首先讲解静态函数:通俗的说静态方法就是函数的形参中没有self。也即,静态函数与类中的静态变量&实例变量都没有半毛钱关系

1
2
3
4
5
6
7
8
9
class Dog(object):

@staticmethod
def bark():
print("my name is Haha")

d1 = Dog()
d1.bark()
# 使用静态方法,输出结果为my name is Haha

那么类函数呢?
1
2
3
4
5
6
7
8
9
10
class Dog(object):
name = "Haha"

@classmethod
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
23
class 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
@property
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Student(object):
@property
def score(self):
return self._score

@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('scofre must between 0-100!')
self._score = value

# 实例化
s = Student()
s.score = 60 # equal to s.set_score(60)
s.score = 101
# Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!

四类函数的小总结:

综上所述,其实我们可以四类函数当做一个逐渐释放权力的过程。当使用静态函数时,类的任何信息你都无权得到;当你使用类函数时,你只可以得到类变量里面的信息,而无法得到实例化之后的类的信息;只有当你使用成员函数,你的权力才得到完整的释放,你既可以使用类变量的信息又可以使用实例化后类的信息。而属性函数则是把一个函数当做属性来看待,这是最好理解的。

我还是不懂何时使用它们怎么办?

记住核心思想:

  1. 类函数主要用途是作为构造函数。
  2. 静态函数的形参没有self
  3. 成员函数用的最多

类的访问控制:单下划线_与双下划线__

  1. “_”:单下划线表示只允许其本身与其子类进行访问
  2. “__”:双下划线表示只允许这个类本身进行访问。

python语言特性

python是动态类型语言

在编写代码的时候可以不指定变量的数据类型

with语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. with语句的语法格式
with content_expression [as targer(s)]:
with-body
# 2. with语句操作文件对象
with open(r'somefileName') as somefile:
for line in somefile:
print line
# ... more code
# 3. 上文代码等价于下文代码:
somefile = open(r'openfileName')
try:
for line in somefile:
print line
# ...more code
finally:
somefile.close()

错误处理

  1. 一个简单易懂的例子:如果某些代码可能会出错
    1
    2
    3
    4
    5
    6
    7
    8
    try:
    r = 10 / 0
    except ZeroDivisonError, e:
    print "ZeroDivisionError", e
    except ValueError, e:
    print "ValueError", e
    finally:
    print 'finally'
  2. 记录错误:打印错误信息,同时让程序继续执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import logging
    def foo(s):
    return 10 / int(s)
    def main():
    try:
    foo('0')
    except StandardError, e:
    logging.exception(e)
    main()
    print "END"

     程序打印完错误信息后会继续执行,并且正常退出。

  3. 抛出错误

    1
    2
    3
    4
    try:
    10 / 0
    except ZeroDivisionError:
    raise ValueError('input error!')

代码trick

再见!中间变量

1
2
3
4
a = 1
b = 2
#不使用中间变量交换两个变量的值
a, b = b, a

字符串逆序

实质是把字符串转换成列表进行操作

1
2
3
4
5
a = "python"
# 方法一:看起来很装逼的方法
print a[::-1] # "nohtyp"
# 方法二:可读性强的方法
print list(a).reverse()

python可以使用连续赋值, 从左至右

1
2
3
4
5
x = [0, 1]
i = 0
# 当我们连续赋值的时候
i, x[i] = 1, 2
# print(x)的结果为[0, 2]:编译器先把1赋值给了i,那么x[i]即为x[1],接下来把2赋值给了x[1]。

矩阵转置

其原理为zip()函数:将对象中对应的元素打包成一个个元组,并且返回由元组组成的列表。这恰好符合矩阵转置的操作

1
2
3
4
mat = [[1, 2, 3], [4, 5, 6]]
# *可以简单理解为解压
print zip(*mat)
#[(1, 4), (2, 5), (3, 6)]

列表转字符串

1
2
3
a = ["Code", "mentor", "Python", "Developer"]
print " ".join(a)
# Code mentor Python Developer

在一个for循环中遍历两个列表

1
2
3
4
list1 = ['a','b','c','d']
list2 = ['apple','boy','cat','dog']
for x,y in zip(list1, list2):
print x 'is' y

同时处理多个文件

1
2
3
4
5
with open(filename1) as fp1, open(filename2) as fp2, open(filename3) as fp3:
for l1 in fp1:
l2 = fp2.readline()
l3 = fp3.readline()
# do something

给字符串前面补“0”

1
2
3
num = "123"
# 向num前面填充0至总位数为5
str_n = num.zfill(5)

回调函数 callback()

官方解释:

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

形象解释:

吃饭、喝水、睡觉就是一个通过大脑调用的动作。如果你把这些动作作为参数传递给大脑,当这些动作被用来真正去执行时,我们就说这是回调函数

代码解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def eat(food):
print "I will eat ", food
def drink(beverage):
print "I will drink ", beverage

def brain(action, target):
return action(target)
```


# __all__与__metaclass__的使用
## __all__
**第一时间**展现了模块的内容大纲,更**清晰**地提供了外部访问的接口。但是要注意,只有列表里内内容才会暴露出去!

请看代码:
### 测试文件foo.py
```py
__all__ = ['pig', 'monkey', 'deer']

deer = 10086
monkey = 10010
def pig():
return "awesome"

测试文件

1
2
3
4
from foo import *
print(bar)
print(monkey)
print(deer)

参考与引用

  1. https://m.baidu.com/?from=844b&vit=fps&nsukey=QL%2FYJKapoliD84rv4ROf08qlZJ83uWDoXzrVj
  2. https://www.cnblogs.com/scf141592/p/5726347.html
  3. https://www.cnblogs.com/crazyrunning/p/6945183.html
  4. https://www.cnblogs.com/polly333/p/8143672.html
  5. https://www.cnblogs.com/crazyrunning/p/6945183.html
  6. https://www.cnblogs.com/imageSet/p/7473326.html
  7. https://www.jianshu.com/p/4bd8a1c93cbe
  8. https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386820062641f3bcc60a4b164f8d91df476445697b9e000
  9. https://www.liaoxuefeng.com/
  10. https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/
  11. https://www.cnblogs.com/alamZ/p/6943869.html
请zzy824喝杯咖啡
0%