面向对象
Python从设计之初就已经是一门面向对象的语言;面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统。面向对象是指一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。 PS. 其实R语言也有面向对象编程,也有面向对象的3个特征:封装、继承、多态
Python类的使用比较广泛,总能在各个Python代码中看到(尤其是伪代码),根据资料理解下Python面向对象的几个概念和简单的使用
具体名字概念(类、方法、实例化、对象等基础名词)可以看:Python3 面向对象,其中主要的就是使用类和对象来编程
其中对于类变量和实例变量最初有点迷糊,但看了下面的例子后就清晰了
class foo:
def __init__(self):
self.x = 10
def add(self, y):
return self.x + y
f = foo()
print(f.x) #5
f.a = 10
foo.a = 20
print(f.x, f.a, foo.a) #5 10 20
foo.b = 30
f.c = 40
f2 = foo()
print(f2.x) # 5
print(f2.a) # 20
print(f2.b) # 30
print(f2.c) # error 'foo' object has no attribute 'c'
以上例子可看出,f.a
和f.c
为实例变量,其只能作用于某一个实例上,因此在f2.c
就报错了;而foo.a
和foo.b
为类变量,其可以被不同对象继承
以上述foo类为例,f = foo()
是实例化类,f.x
则是属性引用(在类中,属性是用变量来表示的);__init__
是特殊方法(在类实例化时自动调用)而add
则是自定义方法,方法可以直接访问实例的数据;self
代表类的实例,比如self.x
就是实例变量,其也是类的方法和普通函数唯一的差别之处,而self.class
则是类,也可以将self替换成其他字符,但是常用一般就这个了
对于方法的调用,在类实例化后可像函数那样使用,如:
f = foo()
print(f.add(10))
在类中可以增加私有变量,使得其在外部无法被访问,如在print(p.__secret)
会报错'private' object has no attribute '__secret'
class private:
__secret = 10
public = 20
p = private()
print(p.public)
print(p.__secret)
类的可以继承,这也是能有效的提高编程的效率,可以减少一些重复的编程工作,即子类可以继承父类的(其实也就是将多个公共的方法放到父类中,然后子类继承父类),如:
class common:
def __init__(self):
self.x = 1
self.y = 2
def add(self, w):
return self.x + self.y + w
c = common()
print(c.add(10))
class foo1(common):
def __init__(self):
common.__init__(self)
self.x += 1
self.y += 2
f1 = foo1()
print(f1.add(10))
从上面代码可看出,父类是common,子类在调用父类时用class foo1(common)
表示foo1类继承了common类,然后用common.__init__
这种形式调用父类的属性,并且不需要再写一遍add
方法即可在子类中使用
模块与包
类似于R包,Python也有将定义的函数和变量封装的封装的方法-模块,以便在其他程序中调用
比如在app.py
脚本中定义了一个函数:
def func(x,y):
print(x, "+", y, "=", x + y)
然后在test.py
脚本中调用app.py
中的func
函数,同时在app.py
所在目录下会生成一个__pycache__
文件夹
import app
app.func(*(1,2))
>1 + 2 = 3
print(app.__name__)
>app
如果不是在当前目录下的模块,可以用sys.path
查看下Python对于模块的搜索路径有哪些
import sys
print(sys.path)
然后可以用dir()
函数来查看模块内定义的名称
dir(app)
Python不仅像上述那样调用方法,还可以调用模块变量和类变量等,如新建一个app_class.py
:
a = 1
b = 2
print(a + b)
def func(x,y):
print(x, "+", y, "=", x + y)
class Myclass:
i = 123
def f(self):
return("Learning Python")
def cf(self):
print("cf:", self.cf)
然后在test.py
中调用app_class.py
,即import app
,输出1 + 2 = 3
,如果再一次import app
则无输出,这是因为模块只有第一次被导入的时候才会被执行,从输出的结果上可看出,模块变量在模块初始化的时候就被执行了,类变量其实也一样,而函数和类的方法则是在初始化后被调用时才执行
app.a
app.func(3,5)
app.Myclass.f(1)
如果你将__name__
设置为__main__
,则可以将模块跟脚本一样执行可接受外部参数,如在代码最后添加一些脚本输出:
if __name__ == "__main__":
import sys
print("Learning Python3", sys.argv[1])
我一直粗略的把R包理解成一大堆R函数的集合,Python对于包的定义则是:
包是一种管理Python模块命名空间的形式
R中是以::
来精确调用不同R包下的函数,而Python则是用.
来实现的
Python包的结构如下:
package1/
__init__.py
subPack1/
__init__.py
module1_1.py
module1_2.py
module1_3.py
subPack2/
__init__.py
module2_1.py
module2_2.py
Python包中必须包含一个__init__.py
文件,用于初始化代码或者__all__
变量赋值;一般我们导入包中特定的子模块会用这种方法:from docx.shared import Inches
,其中shared是docx包的子模块,Inches则是其中的函数;当__init__.py
文件写入__all__ = ["XX1", "XX2", "XX3"]
时,那么在用from package import *
时,只会导入XX1/XX2/XX3子模块,如果没定义的话,则不会导入这三个子模块,而是将包中的所有定义的内容都导入
参考资料:
Python3 面向对象
Python3 模块
http://www.cnblogs.com/tqsummer/archive/2011/01/24/1943273.html
本文出自于http://www.bioinfo-scrounger.com转载请注明出处