初学编程的方法通常由顺序结构开始。这是步骤式的过程性编程,过程式编程方法下的制成品,是一个“大胖子”,为什么呢?假设拆开这个制成品,里面是无数纠缠不清的程序和数据(变量等),数据是给各程序共享的。即任何程序都可以读取或修改它,一个程序接着另一个程序来执行。假设要修改这个制成品,就有一种触一发牵动全身的感觉,例如改了这个程序,可能会影响其他的程序。
OOP(Object-Oriented Programming)面向对象编程
面向对象程序设计的诞生为开发策略带来的极大的改变,使编程的注意力重新从应用程序的逻辑回到其数据上来。换句话说,OOP将焦点从过程式编程转向最终建模的真实实体。这使得应用程序更接近我们周围的现实世界。
OOP达到了软件工程的三个目标:重用性、灵活性和扩展性。
采用面向对象方法可以使系统各部分各司其职、各尽所能; 使其编程的代码更简洁、更易于维护,并且具有更强的可重用性。
类 (class)
类就像是一个模板或设计图,它定义了某个概念或真实事物的性质和行为。
它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和方法两个主要部分。
在OOP术语中,实体的性质和行为的具体定义称为类。
对象 (object)
通过类创建出来的实体称为对象。
对象是系统中用来描述客观事物的一个实体。它是构成系统的一个基本单位,数据与代码都被捆绑在一个实体中。一个对象由一组属性和对这组属性进行操作的一组行为组成。
从更抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组行为的封装体。客观世界是由对象和对象之间的联系组成的。
类与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对对象的抽象就是类.类描述了一组有相同特性(属性)和相同行为(方法)的对象。
关键字class定义自定义的数据类型
class Foo:
def Bar(self):
print 'Bar'
def Hello(self, name):
print 'i am %s' %name
类将现实世界中的概念模拟到计算机程序中
class 类名 :
#定义属性部分
def __init__(self, 初始值1,初始值1, ….):
self.属性1 =初始值1self.属性2 =初始值2
self.属性值n = 初始值n#定义方法部分
方法1:
方法2:
…
方法m:
定义一个类的步骤 :1、定义类名 2、编写类的方法
class Penguin:
def __init__(self, name, month, attack):
self.name = name
self.month = month
self.attack = attack
def eat(self):
self.name = '小星星'
print('我吃鱼呢')
def showMe(self):
print('我的名字是%s,我的攻击性是%d' % (self.name, self.attack))
对象实例化:将类加载到内存中
对象名 = 类名()
class Penguin:
def __init__(self, name, month, attack):
self.name = name
self.month = month
self.attack = attack
def eat(self):
self.name = '小星星'
print('我吃鱼呢')
def showMe(self):
print('我的名字是%s,我的攻击性是%d' % (self.name, self.attack))
small = Penguin('xixi', '5', 100)
类是python的核心和本质。它是python语言的基础,因为类定义了对象的本质。
类定义了一种新的数据类型,可以用新类型来创建该类型的对象。
类(class)是对象(object)的模板,而对象(object)是类的一个实例(instance)。
方法是个“黑匣子”,完成某个特定的应用程序功能,并返回结果
方法调用:执行方法中包含的语句
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
静态方法:由类调用;无默认参数;
class Foo:
def __init__(self, name):
self.name = name
def ord_func(self):
""" 定义普通方法,至少有一个self参数 """
# print self.name
print '普通方法‘
@classmethod
def class_func(cls):
""" 定义类方法,至少有一个cls参数 """
print '类方法'
@staticmethod
def static_func():
""" 定义静态方法 ,无默认参数"""
print '静态方法'
# 调用普通方法
f = Foo()
f.ord_func()
# 调用类方法
Foo.class_func()
# 调用静态方法
Foo.static_func()
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
属性其实是普通方法的变种
属性存在意义是:
访问属性时可以制造出和访问字段完全相同的假象
属性内部进行一系列的逻辑计算,最终将计算结果返回
语法
定义时,在普通方法的基础上添加 @property 装饰器;
定义时,属性仅有一个self参数
调用时,无需括号
方法:foo_obj.func()
属性:foo_obj.prop
class Foo:
def func(self):
pass
# 定义属性
@property
def prop(self):
pass
foo_obj = Foo()
foo_obj.func()
foo_obj.prop #调用属性
class Goods:
@property
def price(self):
print '@property'
@price.setter
def price(self, value):
print '@price.setter'
@price.deleter
def price(self):
print '@price.deleter'
#调用
obj = Goods()
obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数
del obj.price # 自动执行 @price.deleter 修饰的 price 方法
属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
class Goods(object):
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deltter
def price(self, value):
del self.original_price
obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
del obj.price # 删除商品原价
属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
每一个类的成员而言都有两种形式
公有成员,在任何地方都能访问
私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同
私有成员命名时,前两个字符是下划线
私有成员和公有成员的访问限制不同
公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
私有普通字段:仅类内部可以访问;
class C:
def __init__(self):
self.foo = "公有字段"
def func(self):
print(self.foo) # 类内部访问
class D(C):
def show(self):
print(self.foo) # 派生类中访问
obj = C()
obj.foo # 通过对象访问
obj.func() # 类内部访问
obj_son = D();
obj_son.show() # 派生类中访问
class C:
def __init__(self):
self.__foo = "私有字段"
def func(self):
print(self.foo) # 类内部访问
class D(C):
def show(self):
print(self.foo) # 派生类中访问
obj = C()
obj.__foo # 通过对象访问 ==> 错误
obj.func() # 类内部访问 ==> 正确
obj_son = D();
obj_son.show() # 派生类中访问 ==> 错误
私有成员和公有成员的访问限制不同
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问;
class C:
name = "公有静态字段"
def func(self):
print C.name
class D(C):
def show(self):
print C.name
C.name # 类访问
obj = C()
obj.func() # 类内部可以访问
obj_son = D()
obj_son.show() # 派生类中可以访问
class C:
__name = “私有静态字段"
def func(self):
print C.__name
class D(C):
def show(self):
print C.__name
C.__name # 类访问 ==> 错误
obj = C()
obj.func() # 类内部可以访问 ==> 正确
obj_son = D()
obj_son.show() # 派生类中可以访问 ==> 错误
封装 继承 多态
封装就是把对象的属性和行为结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节
信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。
封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的“交叉感染”,使软件错误能够局部化,大大减少查错和排错的难度。
类的封装性带来的优点:隐藏类的实现细节,让使用者只能通过事先定义好的方法来访问数据,可以方便的加入逻辑控制,进行数据检查,限制对属性的不合理操作。便于修改增强代码的可维护性。
封装的实现:
1、在方法中,加入对属性的限制
2、在方法中,对输出的内容进行封装
Class employee :
def __init__(self, name):
self.name = name
def get_age(self):
return $self.age
def set_age(age):
if(age < 0 || age > 130):
return
self.age = age
是指可以让某个类型的对象获得另一个类型的对象的属性的方法。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
生活中,继承的例子随处可见
为什么继承?
开发动物类,其中动物分为猫以及狗,各自的要求如下:
猫
属性:姓名、id
方法:喵喵叫、吃、喝、拉、撒
狗
属性:姓名、id
方法:汪汪叫、吃、喝、拉、撒
继承代码示例:
class Animal:
def eat(self):
print("%s 吃 " % self.name)
def drink(self):
print("%s 喝 " % self.name)
def shit(self):
print("%s 拉 " % self.name)
def pee(self):
print("%s 撒 " % self.name)
class Cat(Animal):
def __init__(self, name):
self.name = name
self.breed = '猫'
def cry(self):
print('喵喵叫')
class Dog(Animal):
def __init__(self, name):
self.name = name
self.breed = ‘狗'
def cry(self):
print(‘汪汪叫')
c1 = Cat('小白家的小黑猫')
c1.eat()
c2 = Cat('小黑的小白猫')
c2.drink()
d1 = Dog('胖子家的小瘦狗')
d1.eat()
Python同样有限的支持多继承形式。多继承的类定义形式如下:
如果父类方法的功能不能满足需求,
可以在子类重写父类的方法,实例如下:
1. 对象的多态性是指在父类中定义的属性或行为被子类继承之后,可以具有不同的数据类型或表现出不同的行为。通过继承过程中的方法重写就可以实现多态
2. 允许不同类的对象对同一消息作出响应。比如同样的加法,把两个时间加在一起和把两个整数加在一起肯定完全不同。
多态
不同的子类对象 调用相同的 父类方法,产生不同的执行结果。
优点
多态可以 增加代码的灵活度
以 继承 和 重写父类方法 为前提
是调用方法的技巧,不会影响到类的内部设计
类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法
class Person:
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I am a Person, my name is %s' % self.name
class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course
def whoAmI(self):
return 'I am a Teacher, my name is %s' % self.name
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I am a Student, my name is %s' % self.name
在一个函数中,如果我们接收一个变量 x,则无论该 x 是
Person、Student还是 Teacher,都可以正确打印出结果:
def who_am_i(x):
print x.whoAmI()
p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')
who_am_i(p)
who_am_i(s)
who_am_i(t)
I am a Person, my name is Tim
I am a Student, my name is Bob
I am a Teacher, my name is Alice
这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
模块
模块实质上就是一个python文件。它是用来组织代码的,意思就是把python代码写到里面,文件名就是模块的名称,test.py test就是模块的名称
包
包,package本质就是一个文件夹,和文件夹不一样的是它有一个__init__.py文件。包是从逻辑上来组织模块的,也就是说它是用来存放模块的,如果想到如其他目录下的模块,那么这个目录必须是一个包才可以导入。
标准模块、标准包
python自带的这些模块,直接import就能用的
import string,random,datetime,os,sys,json,hashlib
第三方模块
别人写好的一些模块,要安装之后才可以用
想实现某个功能,可以先去百度搜一下有没有第三方模块
自己写的python文件
直接在命令行窗口输入命令 pip install open-python
pip在python3.4以上的版本是自带的。但这种方式需要保证pycharm中的Project Interpreter路径是Python安装路径,否则即使窗口显示下载安装成功,依然不能成功import
因为命令行下载下来的第三方安装包存储在Python安装路径\python3\Lib\site-packages
而pycharm import时,是从pycharm->File->Settings->Project Interpreter->设置的路径下\python\Lib\site-packages去取第三方安装包
限制外网无法直接下载时,可以找别人下载好包然后手动安装
1)python官网https://pypi.python.org 搜索包名下载安装包whl
2)安装whl结尾的安装包
地址栏中直接输入cmd,pip install xxx.whl即可安装成功