首页 > 其他 > 详细

面向对象

时间:2020-02-07 16:27:26      阅读:43      评论:0      收藏:0      [点我收藏+]

类有两种属性:属性引用和实例化

属性引用(类名.属性)

class Person:   #定义一个人类
    role = person  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法
        print("person is walking...")


print(Person.role)  #查看人的role属性
print(Person.walk)  #引用人的走路方法,注意,这里不是在调用

实例化:类名加括号就是实例化,会自动出发__init__函数的运行,可以用它为每个实例定制自己的特性

类属性的补充

一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值

二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

面向对象小结:

技术分享图片
class 类名:
    def __init__(self,参数1,参数2):
        self.对象的属性1 = 参数1
        self.对象的属性2 = 参数2

    def 方法名(self):pass

    def 方法名2(self):pass

对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                  #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                  #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                  #结果返回一个对象
对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
View Code

对象之间的交互:

技术分享图片
 1 class Person:  # 定义一个人类
 2     role = person  # 人的角色属性都是人
 3 
 4     def __init__(self, name, aggressivity, life_value):
 5         self.name = name  # 每一个角色都有自己的昵称;
 6         self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
 7         self.life_value = life_value  # 每一个角色都有自己的生命值;
 8 
 9     def attack(self,dog):
10         # 人可以攻击狗,这里的狗也是一个对象。
11         # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
12         dog.life_value -= self.aggressivity
13 
14 class Dog:  # 定义一个狗类
15     role = dog  # 狗的角色属性都是狗
16 
17     def __init__(self, name, breed, aggressivity, life_value):
18         self.name = name  # 每一只狗都有自己的昵称;
19         self.breed = breed  # 每一只狗都有自己的品种;
20         self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
21         self.life_value = life_value  # 每一只狗都有自己的生命值;
22 
23     def bite(self,people):
24         # 狗可以咬人,这里的狗也是一个对象。
25         # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
26         people.life_value -= self.aggressivity
27 
28 p = Person(alex, 10, 100)
29 d = Dog(erha, big_dog, 10, 100)
30 print(d.life_value)   # 查看d的生命值
31 p.attack(d)   # p打了d
32 print(d.life_value)  # d掉了10点血
33  
人狗大战
技术分享图片
 1 from math import pi
 2 
 3 class Circle:
 4     ‘‘‘
 5     定义了一个圆形类;
 6     提供计算面积(area)和周长(perimeter)的方法
 7     ‘‘‘
 8     def __init__(self,radius):
 9         self.radius = radius
10 
11     def area(self):
12          return pi * self.radius * self.radius
13 
14     def perimeter(self):
15         return 2 * pi *self.radius
16 
17 
18 circle =  Circle(10)  #实例化一个圆
19 area1 = circle.area()  #计算圆面积
20 per1 = circle.perimeter()  #计算圆周长
21 print(area1,per1)  #打印圆面积和周长
示例_计算圆周长面积

面向对象的组合方法

技术分享图片
 1 class BirthDate:
 2     def __init__(self,year,month,day):
 3         self.year=year
 4         self.month=month
 5         self.day=day
 6 
 7 class Couse:
 8     def __init__(self,name,price,period):
 9         self.name=name
10         self.price=price
11         self.period=period
12 
13 class Teacher:
14     def __init__(self,name,gender,birth,course):
15         self.name=name 
16         self.gender=gender
17         self.birth=birth
18         self.course=course
19     def teach(self): 
20         print(teaching)
21 
22 p1 = Teacher(alex, male, 
23                    BirthDate(1996, 1, 27),        
24                    Course(python, 180000, 1 year)
25                     )   
26 
27 print(p1.birth.year, p1.birth.month, p1.birth.day)     
28 # 1996 1 27
29 print(p1.course.name, p1.course.price, p1.course.period)
30 # python  180000  1 year
View Code

面向对象的三大特性

继承  多态   封装

1. 继承

一个类可以被多个类继承

一个类可以继承多个父类

技术分享图片
 1 class Animal:
 2     def __init__(self):
 3         print(执行Animal.__init__)
 4         self.func()
 5     def eat(self):
 6         print(%s eating%self)
 7     def drink(self):
 8         print(%s drinkingg % self)
 9     def func(self):
10         print(Animal.func)
11 
12 class Dog(Animal):
13     def guard(self):
14         print(guarding)
15     def func(self):
16         print(Dog.func)
17 dog = Dog()     #  执行Animal.__init__    Dog.func
View Code

注意:

  父类中没有的属性(方法), 在子类中出现,叫做派生属性(方法)

  只要是子类的对象调用,子类中有的名字,一定要用子类的,子类中没有才找父类的,若父类也没用,则报错

  如果还想要用父类的,则单独调用父类:

            父类名.方法名 需要自己传参数

            super.().方法名  不需要自己传参数

技术分享图片
 1 class Animal:
 2     def __init__(self, name, aggr, hp):
 3         self.name = name
 4         self.aggr = aggr
 5         self.hp = hp
 6     def eat(self):
 7         print(eating!!!)
 8 
 9 class Dog(Animal):
10     def __init__(self, name, aggr, hp, kind):  # 定义自己属性
11         # 方法1:直接用父类调用
12         Animal.__init__(self, name, aggr, hp)
13         self.kind = kind  # 派生属性
14 class Person(Animal):
15     def __init__(self, name, aggr, hp, sex):
16         # 方法2: super指定父类
17         super().__init__(name, aggr, hp)
18         self.sex = sex  # 派生属性
19         self.money = 0
20 
21 jin = Dog(金老板,100,500,泰迪)
22 print(jin.name)
23 super(Dog, jin).eat()     # super在外部调用,必须传类名和对象名
派生

总结:

继承
单继承
  先抽象再继承,几个类之间的相同代码抽象出来,成为父类
  子类自己没有的名字,就可以使用父类的方法和属性
  如果子类自己有,一定是先用自己的
  在类中使用self的时候,一定要看清楚self指向谁
多继承
  新式类和经典类:
      多继承寻找名字顺序:新式类广度优先,经典类深度优先
      新式类中有一个类名.mro()查看广度优先的继承顺序
      python3中 有一个super()方法,根据广度优先的顺序查找上一个类

2. 多态 : python天生支持多态

3. 封装

原则: 将不需要对外提供的内容都隐藏起来     

    把属性都隐藏,提供公共方法对其访问

私有变量的私有方法

#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

class A:
    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X=10 #变形为self._A__X
    def __foo(self): #变形为_A__foo
        print(from A)
    def bar(self):
        self.__foo() #只有在类内部才可以通过__foo的形式访问到.
技术分享图片
 1 class Person:
 2     __key = 123
 3     def __init__(self, name, passwd):
 4         self.name = name
 5         self.__passwd = passwd  # 私有变量
 6 
 7 
 8     def get_pwd(self):
 9         return self.__passwd  # 只要在类的内部使用私有属性,就会自动的带上_类名
10 alex = Person(alex, alex3714)
11 print(alex._Person__passwd)     # 对象._类名__属性名
示例

注:

所有的私有 都是在变量的左边加上双下划线
    # 对象的私有属性
    # 类中的私有方法
    # 类中的静态属性
所有的私有的 都不能在类的外部使用

property属性

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

技术分享图片
 1 from math import pi
 2 class Circle:
 3     def __init__(self, r):
 4         self.r = r
 5 
 6     @property   # 伪装成属性
 7     def perimeter(self):
 8         return 2*pi*self.r
 9 
10     def area(self):
11         return self.r**2*pi
12 c1 = Circle(5)
13 print(c1.area())  # 伪 圆的面积
14 print(c1.perimeter)    # 装成属性  被@property伪装成属性 调用该方法名时候 不用加()
View Code

为什么要使用property?

将一个类的函数定义成property属性后,对象再去使用obj.area的时候根本无法察觉自己的area是执行了一个函数计算出来的,这种特性遵循了统一访问的原则

面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

一个静态属性property本质就是实现了get,set,delete三种方法

技术分享图片
 1 class Goods:
 2 
 3     def __init__(self):
 4         # 原价
 5         self.original_price = 100
 6         # 折扣
 7         self.discount = 0.8
 8 
 9     @property
10     def price(self):
11         # 实际价格 = 原价 * 折扣
12         new_price = self.original_price * self.discount
13         return new_price
14 
15     @price.setter   # set时候自动运行
16     def price(self, value):
17         self.original_price = value
18 
19     @price.deleter    # 删除的时候自动运行
20     def price(self):
21         del self.original_price
22 
23 
24 obj = Goods()
25 obj.price         # 获取商品价格
26 obj.price = 200   # 修改商品原价
27 print(obj.price)
28 del obj.price     # 删除商品原价
View Code

classmethod 类方法

技术分享图片
 1 class Goods:
 2     __discount = 0.8
 3     def __init__(self, name, price):
 4         self.name = name
 5         self.__price = price
 6     @property    # @property装饰器装饰后,调用该方法后面不用加()
 7     def price(self):
 8         return self.__price*Goods.__discount
 9 
10     @classmethod   # 把一个方法变成一个类中的方法,这个方法就可以被类调用,不需要依托任何对象
11     def change_discount(cls, new_discount):  # 修改折扣
12         cls.__discount = new_discount
13 apple = Goods(苹果, 5)
14 print(apple.price)    #  4.0
15 Goods.change_discount(0.5)
16 print(apple.price)  #  2.5
17 # 当这个方法的操作只涉及静态属性的时候,就应该使用classmethod来装饰这个方法
View Code

staticmethod方法

class Staticmethod_Demo():
    role = dog

    @staticmethod
    def func():
        print("当普通方法用")

Staticmethod_Demo.func()

# 在完全面向对象的程序中,如果一个函数既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数变成一个静态方法

面向对象的进阶

isinstance和issubclass

isinstance 判断类和对象的关系

issubclass 判断子类和父类的关系

hasattr  getattr  setattr  delattr 四个实现自省的函数

技术分享图片
 1 class Foo:
 2     f = 类的静态变量
 3     def __init__(self,name,age):
 4         self.name=name
 5         self.age=age
 6 
 7     def say_hi(self):
 8         print(hi,%s%self.name)
 9 
10 obj=Foo(egon,73)
11 
12 #检测是否含有某属性
13 print(hasattr(obj,name))
14 print(hasattr(obj,say_hi))
15 
16 #获取属性
17 n=getattr(obj,name)
18 print(n)
19 func=getattr(obj,say_hi)
20 func()   # hi, egon
21 
22 #设置属性
23 setattr(obj,sb,True)
24 setattr(obj,show_name,lambda self:self.name+nb)
25 print(obj.__dict__)
26 print(obj.show_name(obj))   # egonnb
27 
28 #删除属性
29 delattr(obj,age)
30 delattr(obj,show_name)
31 
32 注:反射:是用字符串类型的名字 去操作变量
View Code

类的内置方法

 

# __str__ :打印一个对象的时候,就是调用类名.__str__

class Teacher:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
    def __str__(self):
        return "Teacher‘s object:%s"%self.name
    def __repr__(self):
        return str(self.__dict__)
nezha = Teacher(nezha,1200)
print(nezha)  # Teacher‘s object:nezha
print(%s%nezha)   # Teacher‘s object:nezha
print(str(nezha))  # Teacher‘s object:nezha

print(%r%nezha)  # {‘name‘: ‘nezha‘, ‘salary‘: 1200}
print(repr(nezha))  # {‘name‘: ‘nezha‘, ‘salary‘: 1200}
# %s str()直接打印 实际上都是走的__str__
# %r repr() 都是走的 __repr__
# 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类的__str__
# repr()只会找__repr__,如果没有就找父类

 

__del__

class Foo:
    def __del__(self):
        print(执行我啦)

f1=Foo()
del f1  # 执行我啦

# 析构方法,当对象在内存中被释放时,自动触发执行

__call__

对象后面加括号,触发执行。

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print(__call__)


obj = Foo() # 执行 __init__
obj()       # 执行 __call__

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

 

面向对象

原文:https://www.cnblogs.com/pythoncui/p/12272867.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!