(※python3)
介绍
python是面向对象程序设计Object-oriented programming(OOP)。
对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。
OOP=对象+类+继承+多态+消息。其核心概念就是类和对象。
而python的对象很灵活、概念很广泛。(python自身一个特点)。
面向对象技术:
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
1.定义
类把数据与功能绑定在一起。创建新类就是创建新的对象类型,从而创建该类型的新实例 。
使用class关键字定义类。类的名字一般首字母大写,遵循驼峰命名法。
class Myclass:
def fun1(self):
print("my class!")
·类定义内的语句通常都是函数定义,但允许有其他语句。
·类的内部的定义虽然是def,但是称为“方法”。(方法的描述在下面)
·类定义与函数定义 (def 语句) 一样必须被执行才会起作用。
·进入类定义时,将创建一个新的命名空间,并将其用作局部作用域。
class Classdog:
def __init__(self, name):
self.name = name
self.tricks = [] # 对于传入的每一个self创建一个空列表
def add_trick(self, trick):
self.tricks.append(trick)
2.类的成员
主要是数据属性,创建类时变量形式表示的对象属性称为数据成员或成员属性,用函数形式表示的对象行为称为成员方法,成员属性和成员方法统称为类的成员。属性包括实例属性和类属性。
·一个对象的特征称为"属性"。一个对象的行为称为"方法"。
·属性在代码层面上来看就是变量,方法实际就是函数,通过调用这些函数来完成某些工作。
·进入类定义时,就会创建一个新的命名空间,并把它用作局部作用域。
※一般,实例变量用于每个实例的唯一数据,而类变量用于类的所有实例共享的属性和方法。
※数据属性不需要声明;像局部变量一样,它们将在第一次被赋值时产生。
实例对象
·一般在__init__()中定义,定义和使用必须以self为前缀。
·实例对象所能理解的唯一操作是属性引用。
·外部访问时,作为实例对象,只能通过对象名访问。
类对象
·从结尾处正常离开类定义时,将创建一个类对象。
·类属性属于类对象,可以通过类名或者对象名访问。
·类对象支持两种操作:属性引用和实例化。
class MyClass:
i = 12345
#i是一个类属性
def f(self ,name): # f是一个类对象
f.name=name # name是一个实例对象
※python和其他语言不同的是,支持动态的增加成员。
3.类的使用
在调用类中的方法或属性时都必须遵循一定的规则:调用类的属性或方法分类在类中调用、在类外调用。不同地方调用,调用的方式也会有一定的差距。
属性引用
obj.name。使用class_name.attr_name的方式引用类属性(类名.属性名)。
有效的属性名称是类对象被创建时存在于类命名空间中的所有名称。
类属性可以被赋值,因此可以通过赋值来更改其值。
类的内部调用“自己的”方法时,需要以self为前缀。外部在通过对象名调用方法的时候,不需要传递self。
实例化
实例化对象,并且通过“对象.成员”的方法访问数据成员或成员方法。
格式:实例对象名 = 类名(),实例对象名是新定义的。
class ClassDog:
weignt=100 # 类属性
def __init__(self, name):
self.name = name # 实例属性
self.tricks = []
def add_trick(self, trick):
self.tricks.append(trick)
# 类属性的属性引用
ClassDog.weignt=200 #修改类属性
ClassDog.coolr='blue'#增加新的类属性
# 实例化
dog=ClassDog("John")
dog.add_trick("run")
print(dog.coolr)
·类的实例化使用函数表示法。可以把类对象视为是返回该类的一个新实例的不带参数的函数。
·实例化操作(“调用”类对象)会创建一个空对象。
·许多类喜欢创建带有特定初始状态的自定义实例。 为此类定义可能包含一个名为__init()__的特殊方法。这是一个当创建对象的时候,自动执行的函数。
·像调用函数一样,如果参数传入错误,会引发异常。
class Employee:
#所有员工的基类
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
补充1:
也可以使用以下函数的方式来访问属性:
·getattr(obj, name[, default]) : 访问对象的属性。
·hasattr(obj,name) : 检查是否存在一个属性。
·setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
·delattr(obj, name) : 删除属性。
·isinstance(object,class)可以判断某个方法是否为类的实例。返回值为True||False。
class ClassDog:
def __init__(self, name):
self.name = name
self.tricks = []
def add_trick(self, trick):
self.tricks.append(trick)
d = ClassDog('Fido')
d.add_trick('roll over')
A=1
print(isinstance(d,ClassDog),isinstance(A,ClassDog))
结果:True False。
补充2:
如果同样的属性名称同时出现在实例和类中,则属性查找会优先选择实例。
补充3:内置类属性
- __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
- __doc__ :类的文档字符串
- __name__: 类名
- __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
- __bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
4.私有属性
编程的开闭原则:代码对扩展是开放的,对修改本身是关闭的。
避免直接在对象的外部对变量赋值,python提供了保护机制。(虽然其实并不是严格的访问保护机制。那种仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。)
·私有成员是为了数据封装和保密而设计的。不能在类地外部被使用或直接访问,在类内部的方法中使用时 self.__private_attrs。
·私有方法就是为了只在类的内部使用。
几种特殊成员:
·__XXX:私有成员。
·_XXX:保护成员,不能用from module import*导入。
·__ XXX__:系统定义的特殊成员。
在IDILE下,输入“class.”会自动显示公有成员,“class._"会显示全部成员。
5.方法
粗分为:公有方法;类方法;静态方法;私有方法。
·方法可以通过与普通函数相同的方式引用全局名称。 与方法相关联的全局作用域就是包含其定义的模块。 (类永远不会被作为全局作用域。)
·任何一个作为类属性的函数都为该类的实例定义了一个相应方法。 eg:
# Function defined outside the class
def f1(self, x, y):
return min(x, x+y)
class C:
f = f1
def g(self):
return 'hello world'
h = g
类装饰器
·类装饰器类似于函数装饰器的概念,但它应用于类,它们可以用于管理类自身,或者用来拦截实例创建调用以管理实例。
·Python中一切皆对象,函数也可以当做参数传递。装饰器是接收函数作为参数,添加功能后返回一个新函数的函数(类),装饰器既可以通过函数去实现,也可以通过类去实现。
·Python中通过 @ 使用装饰器。
·装饰器模式就是通过实现一个装饰器,在不修改原来函数的情况下就可以增加一些功能。
import time
class LogTime:
def __call__(self, func):
def _log(*args, **kwargs):
beg = time.time()
res = func(*args, **kwargs)
print('use time: {}'.format(time.time()-beg))
return res
return _log
@LogTime() # 一个需要加括号实现一个装饰器的实例
def mysleep():
time.sleep(1)
mysleep()
·当装饰器带有多个参数的时候, 装饰器函数就需要多加一层嵌套。
def decrator(*dargs, **dkargs):
def wrapper(func):
def _wrapper(*args, **kargs):
print ("装饰器参数:", dargs, dkargs)
print ("函数参数:", args, kargs)
return func(*args, **kargs)
return _wrapper
return wrapper
self参数
在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数。
·类的内部方法类似函数定义,使用参数的方法类似函数使用。
·类的所有实例化方法必须第一个参数是self,(无论是否使用了这个参数)规范。self代表对象本身。
私有方法
以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。
使用@property包装器来包装getter(访问器)和setter(修改器)方法,能够访问和删除到不建议访问|删除的对象。
Python内置的@property装饰器可以把属性变成方法来用,实现的是getter功能。
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
# 访问器 getter方法
@property
def name(self):
return self._name
# 访问器 getter方法
@property
def age(self):
return self._age
# 修改器 setter方法
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在画圈圈' % self._name)
else:
print('%s正在玩游戏' % self._name)
def main():
person = Person('王小王', 12)
person.play()
# 修改属性
person.age = 22
person.play()
# 如果我们修改name属性
person.name = '她' # AttributeError: can't set attribute(不可修改)
if __name__ == '__main__':
main()
类方法
是类所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,也可以有别的参数。但是第一个必须是类对象,类似类中的def定义的普通方法第一个参数要是self一样的道理。
静态方法
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数 。
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def sum(cls,a,b):
return a+b
class Person5:
def __p(self):
print("这是私有属性") #内部函数也同样可以任意之间互相调用
def p1(self):
print("这是p1不是私有方法")
def p2(self):
print("这是p2,可以调用p1,也可以调用私有方法__p")
self.p1()
self.__p()
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def sum(cls,a,b):
return a+b
class People(object):
country = 'china'
@staticmethod
#静态方法,不用定义参数
def getCountry():
return People.country
特殊方法
Python类的特殊方法又称为魔术方法,它是以双下划线包裹一个词的形式出现,例如init。
·__new__与__init__:__new__是用来构造实例的,而__init__只是用来对返回的实例进行一些属性的初始化。(一般首先都会写一个__init__方法去初始化变量,很少__new__)
·__add__:+
·__sub__:-
·__mul__:*
·__pow__:**
·__str__与__repr__:把类的实例变为字符串。
__str__:用于用户调用,__repr__:用于开发人员调用。
`__setattr__、__getattr__、__getattribute__与__delattr__:见上文。
·__del__()。收回对象的时候由系统自动调用,前提是垃圾回收计数器对该对象的引用必须为0。
6.使用实例
可以参考这一篇:https://blog.csdn.net/zcx1203/article/details/89187495
参考:
《Python程序设计(第三版)》清华大学出版社
https://blog.csdn.net/u013380694/article/details/90019571
·https://blog.csdn.net/qq_37189082/article/details/97302030
·https://blog.csdn.net/weixin_38114487/article/details/103955842
·https://blog.csdn.net/qq_36171645/article/details/89340862
·https://docs.python.org/zh-cn/3/tutorial/classes.html
·https://www.runoob.com/python/python-object.html
·https://blog.csdn.net/qq_39314932/article/details/80716295
·https://zhuanlan.zhihu.com/p/79381718
·https://blog.csdn.net/zcx1203/article/details/89187495
"诚恳,踏实,做好手中热爱的事,相信正义。"