面向对象之类

面向过程与面向对象

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

 

posted @ 2018-12-25 21:04  乘月归  阅读(168)  评论(0)    收藏  举报