面向对象,类的属性和 类的方法
面向对象
- 类和对象
- Python类定义
- 类属性
- 类方法
面向过程和面向对象
面向过程 和 面向对象 编程
- 面向过程 编程:函数式编程,C程序,shell等
- 面向对象 编程:C++ ,Java,Python
类和对象
类和对象:是面向对象中的两个重要概念
1.类: 是对事物的抽象,比如:人类,球类
2.对象:是类的一个实例,比如:足球,篮球
实例说明:
球类可以对球的特征和行为进行抽象,然后可以实例化一个真实的球实体出来
静态属性,动态方法
为什么面向对象
面向对象的主要思想是:
- 封装
- 继承
- 多态
这种思想方便解决较为复杂的项目,且维护起来较为容易
类的定义
类定义:
类把需要的变量和函数组合成一起,这样包含称为"封装"
class A(object):
类的结构:
class 类名:
成员变量 - 属性
成员函数 - 方法
class MyClass(object):
def fun(self):
print "i am function"
类的方法中至少有一个参数 self
#!/usr/bin/python
class People(object): # 定义类(class),object可以有,也可以没有
color = 'yellow' #定义了一个静态属性,成员变量
def think(self): #定义了一个动态方法,这个方法里一定要有self,还可以带多个属性,成员函数
self.color = "black" #如果需要调用类里的属性,就要用到self.color来调用该静态属性
print "I am a %s" % self.color #调用动态方法时的输出
print "i am a thinker"
ren = People()
#将类赋值给'ren'这个变量,就是一个对象,即为将类实例化
print ren
# 单纯打印这个'ren'变量是一个对象(object),所以将类实例化后的便是对象(object)
print ren.color #输出,'ren'对象的静态属性,
ren.think() #使用这个类里面的.think()方法
输出结果:
[root@hc python]# python class.py
<__main__.People object at 0x7f646d144690> #打印这个方法的信息
yellow #静态属性的输出结果
I am a black #这里输出的是 ren.think()
i am a thinker
对象的创建
创建对象的过程称之为实例化;
当一个对象被创建后,包含三个方面的特性
- 对象句柄
- 属性
- 方法
句柄用于 区分不同的对象
对象的属性和方法与类中的成员变量和成员函数对应
obj = MyClass()
# 创建类的一个实例(对象)通过对象来调用方法和属性
类的属性
类的属性按使用范围分为公有属性和私有属性,类的属性范围取决于属性的名称
公有属性:
在类中和类外都能调用的属性
私有属性:
不能再类外以及被类以外的函数调用
定义方式:
以"__"双下划线开始的成员变量就是私有属性
可以通过instance._classname__attribute
方式访问
内置属性:由系统在定义类的时候默认添加的,由前后双下划线构成,__dict__ , __module__
#!/usr/bin/python
#coding:utf8
class People(object):
color = 'yellow'
__age = 30 #前面加两个__ 为私有属性,只能内部使用
def think(self):
self.color = "black"
print "I am a %s" % self.color
print "i am a thinker"
print self.__age #调用私有属性
ren = People() #将类实体化
ren.color = 'aaa' #对象内的color属性重新赋值
print ren.color #输出这个对象被新赋值的属性
print People.color() #调用类里的属性,是原来的值,是因为类实体化之前之后是不同的个体
print '-' *50
ren.think() #调用对象里的方法
print '-' *50
print ren.__dict__ #通过对象调用公有的属性,保存到字典里输出
print People.__dict__ #通过类调用内置属性,公私有属性全部保存到字典输出
print '-' *50
print ren._People__age #以这种方法查看对象里的私有属性,测试用
输出结果:
[root@hc python]# python class1.py
# ren = People()
# ren.color = 'aaa'
# print ren.color
# print People.color()
aaa
yellow
--------------------------------------------------
# ren.think()
I am a black
i am a thinker
30 #这是私有属性
--------------------------------------------------
# print ren.__dict__
{'color': 'black'}
# print People.__dict__
{'__module__': '__main__', 'color': 'yellow', '__doc__': None, '__dict__': <attribute '__dict__' of 'People' objects>, '_People__age': 30, '__weakref__': <attribute '__weakref__' of 'People' objects>, 'think': <function think at 0x7fe443e265f0>}
--------------------------------------------------
# print ren._People__age
30
类的方法
- 方法的定义和函数一样,但是需要self 作为第一个参数
- 类方法:
公有方法
私有方法
类方法
静态方法
公有方法:在类中和类外都能调用的方法
私有方法:不能被类的外部调用,在方法前面加上"__"双下划线就是私有方法
self 参数
用于区分函数和类的方法(必须有一个self),self参数表示执行对象本身
方法和函数的区别是:在括号内有没有self,有self就是方法,没有就是函数
self
代表类的本事
通过类调用!
类的方法 (能被类直接调用的叫做类方法)
类方法:
被classmethod()
函数处理过的函数,能被类所调用,也能被对象所调用(是继承的关系)
classmethod
修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
静态方法:
相当于"全局函数",可以被类直接调 用,可以被所有实例化对象共享,通过staticmethod()
定义,
静态方法没有self参数。
装饰器:
@classmethod
# 指定一个类的方法为类方法,通过这个函数classmethod,(单独写需要一个变量来接受值)
#动态方法占用资源比较少,用到了才会加载,但是访问速度比较慢
@staticmethod
#只针对它下面的函数生效,它是将函数转为类的静态方法,静态方法比较占用资源,但是访问速度快
#静态方法无需实例化,但也可以也可以实例化后调用
使用例子
#!/usr/bin/python
#coding:utf8
class People(object):
color = 'yellow'
__age = 30
def think(self):
self.color = "black"
print "I am a %s" % self.color
print "i am a thinker"
print self.__age
def __aaa(self): # 私有方法,只能内部调用
print "使用私有方法 "
def axx(self): #需要使用到一个类的方法内部调用才可以访问到内部的私有方法
self.__aaa()
@classmethod #类方法
def test(x): #修饰符对应的函数不需要实例化,不需要self参数,但第一个参数需要是表示自身类的x参数,可以来调用类的属性,类的方法,实例化对象等。
print x.color
print "动态方法"
@staticmethod #静态方法无需实例化,但也可以也可以实例化后调用
def test1():
print "静态方法"
print "通过实体化后的类访问"
abc = People()
abc.test()
abc.test1()
print "---------------------"
print "通过类访问的"
People.test()
People.test1()
print "---------------------"
abc.axx()
类的内置方法 和 继承
python 内部类
所谓内部类,就是再类的内部定义的类,主要目的是为了更好的抽象实现世界
例子:
汽车是个类,汽车的底盘,轮胎也可以抽象为类,将其定义到汽车类中,则形成内部类,更好的描述汽车类,因为底盘,轮胎是汽车的一部分
内部类的实例化方法
方法1:直接使用外部类调用内部类object_name = outclass_name.inclass_name()
方法2:先对外部类进行实例化,然后再实例化内部类
out_name = outclass_name()
in_name = out_name.inclass_name()
in_name,method()
方法3:公有属性,直接可以通过类直接调用
魔术方法
类的内置方法或者叫做魔术方法
__str__(self)
将输出对象更友好的输出
构造函数与析构函数
构造函数:
用于初始化类的内部状态,Python提供的构造函数是__init__()
;__init__()
方法是可选的,如果不提供,Python会给出一个默认的__init__
方法
析构函数:
用于释放对象占用的资源,Python提供的析构函数是 __del__()
;__del__()
也是可选的。如果不提供,则Python 会在后台提供默认析构函数
垃圾回收机制
1.Python 采用垃圾回收机制来清理不再使用的对象;Python提供gc模块释放不再使用的对象。
2.Python采用"引用计数"的算法方式来处理回收
即:当某个对象在其作用域内不再被其他对象引用的时候,Python就自动清除对象;
3.gc模块的collect()
可以一次性收集所有待处理的对象 print gc.collect()
如果是0则为回收
类的继承
- 继承是面向对象的重要特性之一;
- 继承关系:继承是相对两个雷而言的父子关系,子类继承了父类的所有公有属性和方法
- 继承实现了代码重用
使用继承
继承可以重用已经存在的数据和行为,减少代码的重复编写,Python在类名后使用一对括号来表示继承关系,括号中的类即为父类。
class Myclass(ParentClass)
class Myclass继承了ParentClass类
如果父类定义了__init__
方法,子类必须显示调用父类的__init__
方法:ParentClass.__init__(self,[args...])
如果子类需要扩展父类的行为,可以添加__init__
方法的参数
简单的继承:
#!/usr/bin/python
#-*- coding:utf-8 -*-
class People(object): #New Style 传统方式不加()
color = 'yellow'
def __init__(self, c):
#父类的构造函数,如果self后跟了一个变量,则在继承的子类时需要重写这个构造函数然后引入这个值
print "Init..."
self.dwell = 'Earth' #这是它的初始化变量
def think(self):
print "I am a %s" % self.color
print "I am a thinker "
class Chinese(People): #Chinese继承了People父类
def __init__(self): #则在继承的子类时需要重写这个构造函数然后引入这个值
#People.__init__(self,'red')
#第一种方法可以使用传统的方式 ,super 是第二种方法,不支持传统格式的类
super(Chinese, self).__init__('red')
#使用super函数来继承父类,父类必须是NewStyle,不然会报错
pass
cn = Chinese() #实例化调用这个类
print cn.color #输出里面定义的变量
cn.think() #还能通过继承的类,访问它内部的函数
print cn.dwell #也是会执行内部初始化的变量
super 函数 来继承父类
class Chinese(People):
Chinese继承了People父类
`def __init__(self): `
则在继承的子类时需要重写这个构造函数然后引入这个值super(Chinese, self).__init__('red')
#使用super函数来继承父类,pass
Help on class super in module __builtin__:
class super(object)
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type) -> unbound super object
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super(C, self).meth(arg)
People.__init__(self,'red')
第一种方法可以使用传统的方式 ,super 是第二种方法,不支持传统格式的类
super(Chinese, self).__init__('red')
使用super函数来继承父类,父类必须是NewStyle,不然会报错
继承2
多重继承
Python 支持多重继承,即一个类可以继承多个父类
语法class class_name(Parent_c1,Parent_c2,...)
注意:
当父类中出现多个自定义的__init__
方法时,
多重继承只执行第一个类的__init__
方法
其他不执行
类属性,方法 总结
类的属性-总结
-
类属性,也是共有属性
-
类的私有属性
-
对象的共有属性
-
对象的私有属性
-
内置函数
-
函数的局部变量
-
全局变量
#!/usr/bin/python
#coding:utf8
var5 = '全局变量'
class MyClass(object):
var1 = '类属性,类的公有属性 var1'
__var2 = '类的私有属性 __var2'
def func1(self):
self.var3 = '对象的公有属性 var3'
self.__var4 = '对象的私有属性 __var4'
var5 = '函数的局部变量 var5'
print self.__var4
print var5
def func2(self):
print self.var1
print self.__var2
print self.var3 #需要先调用方法,才能被调用
print self.__var4
print var5 #全局变量!
return '这是函数的返回值,没有return就会出现None'
mc = MyClass()
mc.func1()
print '---------'
print mc.func2()
print '---------'
---------------------------------------------
mc = MyClass() #实例化类
print mc.var1 #私有属性都不能访问
mc.func1() #先调用方法 才能调用内部的公有属性
print mc.func1()
mc1 = MyClass()
print mc1.var3 #没调用内部的方法,所以不能调用
----------------------------------------------
#通过类 ,对象的属性只能通过对象访问,
print MyClass.var1 #访问类的公有属性 可以
print MyClass.var2 #访问类的私有属性 不可以
mc = MyClass()
mc.fun1
mc.fun2
print '-' * 50
print mc.__dict__ #返回一个字典,里面包含的是'类的内置属性'
print '-' * 50
print MyClass.__dict__ #通过类来调用'内置属性',返回一个字典,里面包含的类来调用'内置属性'
类方法总结
-
公有方法
-
私有方法
-
类方法
-
静态方法
-
内置方法
#!/usr/bin/python
#coding:utf8
class MyClass(object):
name = 'Test'
def __init__(self): #如果加了内部的构造函数,即当前的类别实例化会,
self.func1() #会自动加载,并初始化里面的内容
self.__func2()
self.classFun() #类方法,静态方法 这两种都可以通过对象来调用
self.staticFun()
def func1(self):
print self.name,
print "我是公有方法"
# self.__func2()
def __func2(self):
print self.name,
print "我是私有方法"
@classmethod #修饰器,这样就将类里的方法,转为类方法然后外部调用
def classFun(self):
print self.name,
print "我是类方法"
@staticmethod #修饰器
def staticFun(): #静态方法不能有 self 方法
print MyClass.name, #因为是静态的,需要类名来调用
print "我是静态方法"
mc = MyClass() #实例化
mc.func1()
mc.__fun2() #直接调用不行。必须在内部调用,在func1里面调用才可以
------------------------------------------------------------------------------------
MyClass.classFun() #类方法,需要加修饰器才可以再外部调用
MyClass.staticFun() #静态方法,需要加修饰器才可以再外部调用
#类方法,静态方法 这两种都可以通过对象来调用
rc脚本(类的定义与脚本的结构)
#!/usr/bin/python
import sys
import os
from subprocess import Popen, PIPE
#调用系统bash 启动,stdout的标准输出通过这个PIPE管道符传入一个临时文件里
class Process(object):
'''memcached rc script''' #注释
def __init__(self, name, program, args, workdir): #类实例化的时候,初始化传递的参数
self.name = name
self.program = program #初始化属性
self.args = args
self.workdir = workdir
def _init(self): #这里是一个下划线,是一个普通的方法
'''/var/tmp/memcached'''
if not os.path.exists(self.workdir): # 判断目标不存在,则创建,进入该目录
os.mkdir(self.workdir) # mkdir 创建目录
os.chdir(self.workdir) # chdir 进入该目录
def _pidFile(self):
'''/var/tmp/memcached/memcached.pid'''
return os.path.join(self.workdir, "%s.pid" % self.name)
#将目录连接到一起,然后返回这个结果
def _writhPid(self):
if selp.pid: #判断这个pid 是否有值,有值则写入文件
with open(self._pidFile(),'w') as fd:
fd.write(str(self.pid))
def start(self): #类里的方法
self._init() #这个方法判断这个目录在不在,不在就创建。
cmd = self.program + ' ' + self.args #启动脚本的路径 + ' ' + 启动选项参数
p = Popen(cmd, stdout=PIPE, shell=True)
# 这条是执行命令,stdout=PIPE:是将标准输出传给管道,传给一个临时文件里
self.pid = p.pid #用了Popen里的一个pid方法输出PID
self._wirthPid() #调用方法写PID 这个值
print "%s start Sucessful" % self.name
def _getPid(self):
p = Popen(['pidof',self.name],stdout=PEPI)
pid = p.stdout.read().strip()
# strip() 去除收尾的空格,换行等。可以执行去掉的字符,需要在括号内写
return pid
def stop(self):
self._getPid()
if pid: #判断这个不为空则执行
os.kill(int(pid),15)
#调用系统命令 kill 进程,用kill -15 相当正常退出,kill()里面需要两个参数,一个是PID和等级
if os.path.exists(self._pidFile()):
os.remove(self._pifFile())
print " %s is stop" % self.name
def restart(self):
self.stop()
self.start()
def status(self):
pid = self._getPid()
if pid:
print "%s is runing" % self.name
elif pid:
print "%s in stopped" % self.name
def help(self):
print "Usage: %s {start|stop|status|restart}" % __file__
# __file__ 打印这个内置属性,则是该文件名
def main(): #一个主体函数
name = 'memcached' #程序名
prog = '/usr/bin/memcached' #程序的启动脚本的路径
args = '-u nobody -p 11211 -c 1024 -m 64' #启动时带的参数
wd = '/var/tmp/memcached' #程序所在的路径
pm = Process(name = name, #上面的参数 传入类的属性里去
program = prog,
args = args,
workdir = wd)
try: #处理输入的异常
cmd = sys.argv[1] #取输入脚本的第一个值 比如,start,stop等等。。
except IndexError, e: #except 异常的捕捉
print "Option error"
sys.exit()
if cmd == 'start': #判断输入的类型
pm.start() # 实例化后的类 进行调用内部的方法
elif cmd == 'stop':
pm.stop()
elif cmd == 'restart':
pm.restart()
elif cmd == 'status':
pm.status()
else:
pm.help()
if __name__ == '__main__':
#调用使用 main() 函数,print(__name__) 打印的输出就等于__main__
main() #这里等同于启动python程序的意思
Linux kill 命令
9和15 的区别,最好还是用15,这样相当于正常退出
SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号。
linux 命令
echo $$ #当前PID的bash 进程
tty #显示当前终端号
pidof #取一个进程的PID
关于 get pid 的问题
from subprocess import Popen, PIPE #先加载模块
p = Popen(['pidof','memcached'], stdout=PIPE) #将Popen 实例化 给p
p.pid #p调用pid方法 ,这个PID 是 pidof命令的进程的PID
28675
pid = p.stdout.read() #这个PID才是我memcached的进程PID
pid
'28001
'
pid.strip() #用strip() 字符串方法 去掉 特殊字符
'28001'