面向对象之类
面向过程与面向对象
1. 面向过程
面向过程就是一切以过程为核心,过程就是解决问题的步骤,把一个大的问题分解成小的问题,再分解成更小的问题,一直这样直到问题能用一步解决为止,面向过程编程就像非常像工厂的流水线,先做什么,再做什么,最后做什么,一环套一环,是一种比较传统的编程方式。
面向过程的优点:问题流程化,编写相对简单;缺点是每个问题都要编写一套流程,可扩展性差。
2. 面向对象
面向对象编程(OOP)全称为Object Oriented Programming,个人认为翻译成基于对象编程更合适,也就是一切以对象(object,不是女朋友,别想歪了~)为核心。对象就是个体,你是对象,你家的大橘也是对象,路边的一棵树,一栋房子都是对象,整个现实世界都是由对象构成的。计算机的世界是对现实世界的模拟,也就是是创建出一个个对象,然后操纵它们来完成一定的工作。
面向对象编程
前面提到的面向对象编程就是创建出一个个对象,然后用这些对象完成我们想做的事,那么怎么创建对象呢?这里我们就要用到类这个概念。类就是具有相同属性、能够完成相同动作的事物的总称。比如小狗都有毛,都有耳朵,都能啃骨头,小狗就是一个类,我们可以根据这个类创建出很多不同毛发不同耳朵的小狗。创建方法明天再写
类的成员--变量
类的变量分为两大类:
1. 实例变量(字段)
2. 类变量(静态变量)
1 class Person: 2 country = "中国" # 类变量,所有该类的对象共享这个变量(公用) 3 4 def __init__(self, name, num, birthday): 5 self.name = name 6 self.num = num 7 self.birthday = birthday 8 9 10 p1 = Person("Sansa", 18, "1995年6月19日") 11 p2 = Person("Lucy", 19, "1996年9月2日") 12 print(p1.birthday) 13 print(p2.name) 14 print(p1.country) 15 print(p2.country)
输出
1995年6月19日
Lucy
中国
中国
Process finished with exit code 0
可以看到p1,p2的name,num,birthday都是指向自己,每个人的值都不一样,而country是一样的,这是因为country这个属性是属于类的,在类里面专门开辟一个内存空间来存储这个变量,我们可以通过查看内存地址类来验证
1 print(id(p1.name)) 2 print(id(p2.name)) 3 print(id(p1.num)) 4 print(id(p2.num)) 5 print(id(p1.country)) 6 print(id(p2.country))
输出
2098270012280
2098270145200
1445228096
1445228128
2098270163168
2098270163168
Process finished with exit code 0
可以看到p1,p2的name,num的内存地址不一样,而country一样,把country的值改了,各个对象的值都跟着变了,来看代码
1 Person.country = "大清" 2 print(p1.country) 3 print(p2.country)
输出
大清
大清
Process finished with exit code 0
注意这里的country一般用类名来访问和修改,通过对象名也可以访问,但不能修改,来看一段代码
1 p1.country = "大秦" 2 print(p1.country) 3 print(p2.country) 4 print(id(p1.country)) 5 print(id(p2.country))
输出
大秦 中国 2183152324920 2183152324832 Process finished with exit code 0
大家可能会疑惑:第一行把p1.country设置为大秦,为什么打印出来的p2.country还是中国呢?这是因为用对象名访问类变量并不能修改类变量的值,第一行的赋值语句实际上是在p1内部创建了一个与类变量同名的实例变量,再打印p1.country时,打印的就是实例变量而不是类变量,p1.country和p2.country的内存地址不一样也可以证明这一点。
下面通过程序来记录当前类被创建了多少个对象
1 class Foo: 2 count = 0 3 4 def __init__(self): 5 Foo.count += 1 # 访问类变量count的方式是类名.count 6 7 8 foo1 = Foo() 9 foo2 = Foo() 10 print(Foo.count)
输出
2
Process finished with exit code 0
类的成员--方法
1. 实例方法(成员方法)
2. 静态方法
3. 类方法
实例方法
对象直接访问的方法就是成员方法,我们平时用的最多的就是成员方法
1 class Computer: 2 # 实例方法 3 def play(self): 4 print("我的电脑可以玩儿") 5 6 7 c = Computer() 8 c.play()
输出
我的电脑可以玩儿
Process finished with exit code 0
静态方法
静态方法不需要我们给方法传递self,也就是说,当一个方法不需要使用到成员变量的时候,就可以使用静态方法。静态方法需要在方法前面添加一个@staticmethod,静态方法和静态变量一样,都是使用类名直接访问和调用的
1 class Computer: 2 # 实例方法 3 @staticmethod 4 def fare(): # 没有self 5 print("我的电脑可以煎鸡蛋") 6 7 8 Computer.fare() # 访问静态方法不需要使用到成员变量,也不需要创建对象
输出
我的电脑可以煎鸡蛋
Process finished with exit code 0
类方法
类方法和静态方法差不多,只不过类方法在调用的时候也不需要传递实例对象,但是系统会自动地把类传递给第一个参数,类方法在编写的时候,需要在前面加上@classmethod
1 class Computer: 2 def play(self): 3 print("我的电脑可以玩") 4 5 @staticmethod 6 def fare(): 7 print("我的电脑可以煎鸡蛋") 8 9 @classmethod 10 def cal(cls, a, b): # 系统默认加上cls 11 print(cls) 12 return a + b 13 14 15 print(Computer.cal(2, 3))
输出
<class '__main__.Computer'> 5 Process finished with exit code 0
静态方法/类方法不能访问实例变量,但可以访问类变量
1 class Computer: 2 size = 15.6 3 4 def __init__(self, brand, model, year): 5 self.brand = brand 6 self.model = model 7 self.year = year 8 9 def play(self): 10 print("我的%s电脑可以玩" % self.brand) 11 12 @staticmethod 13 def fare(): 14 print("我的%s电脑可以煎鸡蛋" % self.brand) 15 print("我的电脑是%s寸" % Computer.size)
执行结果
Traceback (most recent call last): File "D:/类.py", line 98, in <module> Computer.fare() File "D:/类.py", line 87, in fare print("我的%s电脑可以煎鸡蛋" % self.brand) NameError: name 'self' is not defined Process finished with exit code 1
说明静态方法不能访问实例变量,那么可以访问类变量吗,来看看
1 class Computer: 2 size = 15.6 3 4 def __init__(self, brand, model, year): 5 self.brand = brand 6 self.model = model 7 self.year = year 8 9 def play(self): 10 print("我的%s电脑可以玩" % self.brand) 11 12 @staticmethod 13 def fare(): 14 # print("我的%s电脑可以煎鸡蛋" % self.brand) 15 print("我的电脑是%s寸" % Computer.size)
输出结果
我的电脑是15.6寸
Process finished with exit code 0
可见静态方法是可以访问类变量的
属性
应用场景:存储用户的年龄,年龄一直在变,我们可以通过存储出生年月然后通过计算得到年龄,这里的年龄就可以用属性来描述。属性相当于方法改造过来的一种变量
1 import time 2 3 4 class Person: 5 def __init__(self): 6 pass 7 @property 8 def age(self): 9 return int(time.strftime("%Y")) - 1993 # 格式化时间-当前时间 10 11 12 p = Person() 13 age = p.age 14 print(age)
输出
25
Process finished with exit code 0
私有
一般不提倡设置和使用私有信息,写法为前面加上__
实例变量和类变量/静态变量都可以设置私有
1 class Person: 2 def __init__(self, wife, mimi): 3 self.__wife = wife 4 self.__mimi = mimi 5 6 def gaosuni(self): 7 print("大喇叭开始广播了") 8 return self.__mimi # 通过公共方法获取私有内容,供外界访问 9 10 11 p1 = Person("sansa", "bra") 12 m = p1.gaosuni() # 外界访问 13 print(m)
输出
大喇叭开始广播了
bra
Process finished with exit code 0
私有方法
只能在类中自己调用,类外面不能访问
1 class Person: 2 def __init__(self): 3 pass 4 5 def __date(self): 6 print("I have a date today") 7 8 9 p = Person() 10 p.__date()
输出
Traceback (most recent call last): File "D:/类.py", line 145, in <module> p.__date() AttributeError: 'Person' object has no attribute '__date' Process finished with exit code 1
可以看到类外面是不能调用私有方法的。还有一点要补充的是,对于私有内容,子类是无法继承的
1 class Girl: 2 __type = "beauty" 3 4 5 class Girlfriend(Girl): 6 pass 7 8 9 print(Girlfriend.__type)
输出
Traceback (most recent call last): File "D:/类.py", line 155, in <module> print(Girlfriend.__type) AttributeError: type object 'Girlfriend' has no attribute '__type' Process finished with exit code 1

浙公网安备 33010602011771号