面向过程编程(百度 or google):
(1) 定义:
(2)对比于函数式和面向过程编程的优缺点:
python中的类:
(1)定义(百度 or google):
(2)说明: python中的类由属性与方法构成,类中的方法是对属性的使用或修改。对比于游戏中的角色人物,有力量值,法术值,物防,法防等这些属性,而游戏角色的技能是对这些属性的利用,游戏角色的升级或掉级会修改这些值,对于类而言,它的技能就是方法,这些方法或修改或使用类的属性。
(3)应用:类一般是对某样真实物体的抽象建模,它用于在计算机程序中批量产生这类东西。就好比在游戏中,一种角色,有成千上万的玩家使用,由于每个玩家的等级,装备等差异,属性值各不相同,但这些角色的属性都是由最基础的构成(力量值,法术值,物防,法防等),角色的技能效果也是一样的,对于类而言只需修改一下基础属性就可以在程序中批量的创建它们。
(4)python中类的语法:
class Person(object): ethnicity = "Humanity" def __init__(self, name, age, wages): ''' 构造函数,用于初始化对象的属性 ''' self.name = name self.__age = age #私有属性 self.wages = wages pass def __del__(self): ''' 析构函数,在对象被销毁或程序结束时执行 ''' print("__del()__") pass def func1(self): ''' 第一个方法,展示对属性的利用 ''' print("This is func1()") print("%s: age:%s wages:%s" % (self.name, self.__age, self.wages)) pass def func2(self): ''' 第二个方法,展示对属性的修改 ''' self.__age += 1 self.wages -=1500 print("This is func2()") print("%s: age:%d wages:%d" % (self.name, self.__age, self.wages)) pass def get_info(self): print("name:%s age:%s wages:%s ethnicity:%s" % (self.name, self.__age, self.wages, self.ethnicity)) person_1 = Person("Jack", 21, 10000) #用类实例化一个人 print(person_1.name) #调用类中的属性 person_1.func1() #调用类中的方法 person_1.func2() person_1.get_info() >>> Jack This is func1() Jack: age:21 wages:10000 This is func2() Jack: age:22 wages:8500 name:Jack #get_info执行结果 age:22 wages:8500
ethnicity:Humanity __del()__ #析构函数执行结果
在本例中对一个人用类进行了最基本最简单的建模,演示了python中类的语法和应用。
构造函数:用于初始化对象的基本属性。比如在本例中对象的(name, age, wages)三个基本属性,用构造函数进行初始赋值。
类属性:定义在构造函数上面的变量。一般批量制造出的对象的公共属性(且不会被经常改变)用这种方式定义。(比如游戏角色的种族,职业等)
实例属性:定义在构造函数里的变量。批量产生的对象的差异属性或可能会被经常改变的默认属性(以默认参数实现)用这种方式定义。(比如玩家的昵称,等级等)
析构函数:在对象被销毁或程序结束时自动执行。一般用于关闭类中其他方法打开的临时文件或数据库连接。
私有属性:只能通过类中的方法修改或查询,在类的外部无法被访问。 定义时只需在变量名前加上‘__’即可,可以使用同样的方法定义私有方法(在函数命前加上‘__’,一般用于类中某些方法的更底层的方法,外部无法调用)。在本例中__age就是私有属性,它无法通过像person_1.name的这种方式使用。
(5)类的继承与派生:
class Person(object): #本例中的基类 def __init__(self, name, gender, age): self.name = name self.gender = gender self.age = age def my_message(self): print('''-----message of %s----- name:%s gender:%s age:%s''' %(self.name, self.name, self.gender, self.age)) class Worker(Person): #Worker类继承Person类 def __init__(self, name, gender, age, wage): super(Worker, self).__init__(name, gender, age) #调用父类的构造函数,调用父类的其他方法只需改变函数名和参数 self.wage = wage def get_paid(self): print("my wage: $%s" % self.wage) class Driver(Worker): #Driver类继承Worker类 def __init__(self, name, gender, age, wage, driving_age): super(Driver, self).__init__(name, gender, age, wage) self.driving_age = driving_age def drive(self): print("My driving age is %s years", self.driving_age) print("driving...") print("First Class") p1 = Person("John", 'M', 35) p1.my_message() #调用类内方法 print(' ') print("Second Class") w1 = Worker("Lily", 'F', 30, 5000) w1.my_message() #调用父类方法 w1.get_paid() #调用类内方法 print(' ') print("Third Class") d1 = Driver("Jack", 'M', 40, 7500, 15) d1.my_message() #调用父类的父类方法 d1.get_paid() #调用父类方法 d1.drive() #调用类内方法 >>> First Class -----message of John----- name:John gender:M age:35 Second Class -----message of Lily----- name:Lily gender:F age:30 my wage: $5000 Third Class -----message of Jack----- name:Jack gender:M age:40 my wage: $7500 My driving age is %s years 15 driving...
说明:好比游戏角色的觉醒(或者转职), 往往会在原来的角色基础上增加新的属性和技能。在类中同样有这一操作,叫做类的继承与派生。程序中的类如果只有继承,那不如直接用原来的类,所以一般来讲有继承就有派生。而继承与派生的作用就是为类增添新属性与新方法。
Worker类:Worker类继承了Person类,相比与基类他增加了一个属性(wage)和一个方法(get_paid())
Driver类:同理继承了Worker类, 增加了一个属性(driving_age)和一个方法(drive())
可以看到worker类它既可以使用自己的属性和方法,它也可以使用父类的属性和方法,这就好比对现实的一种分类下面又有许多更详细的分类。现实中,人是一个总类,下面可以分出工人,白领,公务员,企业家等等,而工人又可以分出石油工人,铁路工人,环卫工人等等,但自上而下,它们都有共性,自下而上,它们又有差异。而计算机程序要对现实世界抽像于是便有了类的继承与派生。
而观察Driver类,它不仅可以使用自己和父类的属性和方法,还可以使用父类的父类的属性和方法(可以说成隔代继承)。所以,我们可以知道类可以多代继承,而且不管继承了多少代都可以使用类的第一代到它本身中的任何一个方法或属性。
注意:如果子类中的属性或方法与父类中的相同,以子类中的为准,好比全局变量与局部变量。(类是面向对象的最重要部分,学习计算机程序的我们都应认真学习。)
python中的反射:
在面向对象编程的过程中,难免会需要根据用户不同的输入灵活的对对象进行动态操作。
所谓反射,就是利用字符串直接对对象中的属性或方法的进行操作的一种方式,python中用以进行反射操作的有一下几种内置函数:
getattr():
函数原型:getattr(object, name[, default]) -> value
可使用getattr()直接对对象中的属性进行调用:
a = getattr(x, 'y') # 相当于 a = x.y 若y为属性,则a使x.y的值,若y为方法,则a()与x.y()效果相同。
hasattr():
函数原型:hasattr(object, name)
可使用hasattr()判断对象中是否有名为name的属性:
b = hasatrr(x, 'y') #若对象x中存在x.y(无论y是属性还是方法),则b=True,否则b = False。
setatrr():
函数原型:setattr(x, y, v)
可使用setattr()为对象添加方法或属性:
setattr(x, ‘y’, c) 相当于 x.y = c
delattr():
函数原型:delattr(x, y)
可使用delattr()删除对象的属性或方法:
delattr(x, 'y') 相当于 del x.y
注意:delattr()只能删除属性,不能删除方法。
用法示例:
1 class Person(object): 2 def __init__(self, name, gender, age): 3 self.name = name 4 self.gender = gender 5 self.age = age 6 7 def my_message(self): 8 print('''-----message of %s----- 9 name:%s 10 gender:%s 11 age:%s''' %(self.name, self.name, self.gender, self.age)) 12 13 class Worker(Person): #Worker类继承Person类 14 def __init__(self, name, gender, age, wage): 15 super(Worker, self).__init__(name, gender, age) #调用父类的构造函数,调用父类的其他方法只需改变函数名和参数 16 self.wage = wage 17 18 def get_paid(self): 19 print("my wages: $%s" % self.wage) 20 21 def talk(self): 22 print("%s is talking..." % self.name) 23 24 25 26 w1 = Worker("Lily", 'F', 30, 5000) 27 #getattr()用法示例 28 print("这是getattr()的用法") 29 a = getattr(w1, 'name') 30 print(a) 31 func1 = getattr(w1, 'get_paid') 32 func1() 33 print(' ') 34 #hasattr()用法示例 35 print("这是hasattr()的用法") 36 print(hasattr(w1, 'abcd')) 37 print(hasattr(w1, 'name')) 38 print(hasattr(w1, 'get_paid')) 39 print(' ') 40 #setattr()用法示例 41 print("这是setattr()的用法") 42 setattr(w1, 'tell', talk) 43 w1.tell(w1) 44 gender = 'F' 45 setattr(w1, 'sex', gender) 46 print(w1.sex) 47 print(' ') 48 #delattr()用法示例 49 print("这是delattr()的用法") 50 delattr(w1, 'name') 51 print(hasattr(w1, 'name')) 52 53 54 >>> 55 这是getattr()的用法 56 Lily 57 my wages: $5000 58 59 60 这是hasattr()的用法 61 False 62 True 63 True 64 65 66 这是setattr()的用法 67 Lily is talking... 68 F 69 70 71 这是delattr()的用法 72 False