面向对象

类:class

类是抽象的概念,是万事万物的抽象,是一类事物的共同特性的集合

用计算机语言来描述类,就是属性和方法的集合


对象instance、object

对象是类的具象,是一个实体

对于我们每个人这个个体,都是抽象概念人类的不同的实体

 

举例:

你吃鱼

你,就是对象,鱼也是对象,吃就是动作

你是具体的人,是具体的对象,你属于人类,人类是个抽象的概念,是无数个具体的个体的抽象

 

鱼也是具体的对象,就是你吃的这一条具体的鱼,这条鱼属于鱼类,是无数条具体的鱼抽象出来的概念

 

吃,是动作,也是操作,也是方法,这个吃是你的动作,也就是人类具有的方法。

 

属性,它是对象状态的抽象,用数据结构来描述

因为属性是放在类里面的,而类是个抽象概念,所以说属性也是抽象的概念

操作(方法),是个动作(说到底就是函数),它是对象行为的抽象,用操作名和实现该操作的方法来描述

 

面向对象的三要素:

1、封装:

  1. 组装:将数据和操作组装到一起
  2. 隐藏数据:对外只暴露一些接口,通过接口访问对象,比如驾驶员驾驶汽车,不需要了解汽车的构造细节,只要知道使用什么部件,怎么驾驶就行,踩了油门就能跑,可以不了解后面的机动原理 

2、继承:

  1. 多复用,继承来的就不用自己写了
  2. 多继承少修改,使用继承来改变,来体现个性

3、多态:

  1. 面向对象编程最灵活的地方,动态绑定

 

人类就是封装

人类继承自动物类,孩子继承父母特性,分为单一继承,多继承

多态,继承自动物类的人类、狗类的操作“吃”不同

 

class ClassName

       语句块

1、必须使用class关键字

2、类名必须是用大驼峰命名

3、类定义完成后,就产生了一个类对象,绑定到了ClassName上

 

class MyClass:
    """A example class"""
    x = 'abc'  # 类属性

    def foo(self):  # 类属性foo,也是方法
        return 'My class'


print(MyClass.x)
print(MyClass.foo)
print(MyClass.__doc__)
a = MyClass()  # 实例化
print(a.foo())

类对象,类的定义就会生成一个类对象

类的属性,类定义中的变量和类中定义的方法都是类的属性、

类变量,x是MyClass的变量

在MyClass中,x、foo都是类的属性,__doc__也是类的属性

foo方法是类的属性,如同吃是人类的方法,但是每一个具体的人才能吃东西,也就是说吃是人的实例才能调用方法

foo是method方法对象,不是普通的函数对象function,它必须至少有一个参数,且第一个参数必须是self(self可换名)

self代指当前实例本身

 

实例化:a = MyClass(),就是调用类的实例化方法,完成实例化,实例化后获得的实例,是不同的实例,即使是使用

同样的参数实例化,也得到不一样的对象

 

class Person:
    x = 'abc'
    def __init__(self, name, age):
        self.name = name     #实例的属性  python中以self开头的
        self.age = age

tom = Person('tom', 28)
jerry = Person('tom', 28)
print(tom == jerry)         False
print(tom is jerry)         False

#实例的属性  python中以self开头的

Python类实例化后,会自动调用__init__方法,这个方法第一个参数必须留给self,其它参数随意

MyClass()实际上调用的是__init__(self)方法,可以不定义,如果没有定义将隐式的调用

其作用:对实例进行初始化(并非创建,创建好了才能初始化,也只能在这之后初始化,修改不是初始化)

初始化函数可以多参,第一个位置必须是self,例如init(self, name, age)

class Person:
    x = 'abc'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def showage(self, t, y):
        print('{} is {}.类属性x为{}'.format(self.name, self.age, self.x))
        self.age = t
        Person.x = y


tom = Person('tom', 28)
jerry = Person('jerry', 30)
jerry.age += 1
print(tom.x, jerry.x)
print(tom.name, jerry.age)
print(jerry.name, jerry.age)
jerry.showage(100, 'a')
print(jerry.age)
print(jerry.x)

输出:

abc abc
tom 31
jerry 31
jerry is 31.类属性x为abc
100
a

__init__()方法不能有返回值,就是只能返回None

 

实例对象:类实例化后一定会获得一个对象,就是实例对象

上面的jerry,tom就是Peron类的实例

__init__方法的第一个参数self就是指代某一个实例

class MyClass:
    def __init__(self):
        print('self in init = {}'.format(id(self)))


c = MyClass()
print('c = {}'.format(id(c)))
print(type(MyClass))
print(MyClass.__class__)

out:
self in init = 2046181910960
c = 2046181910960
<class 'type'>
<class 'type'>

__name__  对象名

__class__  对象的类型

__dict__     对象的属性字典

__qualname__  类的限定名 

class Person:
    """hello"""

    x = 'abc'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def showage(self):
        print(self.name, self.age)


tom = Person('tom', 28)
jerry = Person('jerry', 30)

print(1, Person.__class__)
print(2, tom.__class__)   # 返回的是一个类
print(3, tom.__class__.__qualname__)  # 返回的是字符串
print(4, tom.__class__.__name__)  # 返回的是字符串

print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')

print(5, isinstance(jerry, tom.__class__))  # jerry是不是tom.__class__这个类型的
print(6, isinstance(jerry, int.__class__))
print(7, int.__class__)

print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')

print(8, Person.__dict__)
print(9, tom.__dict__)
print(10, jerry.__dict__)

print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')

print('hehe', sorted(Person.__dict__.items()), end='\n\n')
print('heihei', sorted(tom.__dict__.items()), end='\n\n')
输出:
1 <class 'type'>
2 <class '__main__.Person'>
3 Person
4 Person
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 True
6 False
7 <class 'type'>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 {'x': 'abc', '__doc__': 'hello', '__init__': <function Person.__init__ at 0x00000264F7B65AE8>, '__module__': '__main__', 'showage': <function Person.showage at 0x00000264F7B65EA0>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__dict__': <attribute '__dict__' of 'Person' objects>}
9 {'age': 28, 'name': 'tom'}
10 {'age': 30, 'name': 'jerry'}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hehe [('__dict__', <attribute '__dict__' of 'Person' objects>), ('__doc__', 'hello'), ('__init__', <function Person.__init__ at 0x00000264F7B65AE8>), ('__module__', '__main__'), ('__weakref__', <attribute '__weakref__' of 'Person' objects>), ('showage', <function Person.showage at 0x00000264F7B65EA0>), ('x', 'abc')]

heihei [('age', 28), ('name', 'tom')]

类属性保存在类的__dict__中,实例属性保存在实例的__dict__中,如果从实例访问类的属性,

就需要借助__class__找到所属的类 

class Person:
    age = 3
    height = 176

    def __init__(self, name, age=18):
        self.name = name
        self.age = age


Person.age = 30
tom = Person('tom')
jerry = Person('jerry', 20)
print(Person.age, tom.age, jerry.age)
print(Person.height, tom.height, jerry.height)
Person.height += 20
print(Person.height, tom.height, jerry.height)

tom.height = 186
print(Person.height, tom.height, jerry.height)

jerry.height += 10
print(Person.height, tom.height, jerry.height)

print(tom.__dict__)
print(jerry.__dict__)
print(Person.__dict__)
输出:
30 18 20
176 176 176
196 196 196
196 186 196
196 186 206
{'name': 'tom', 'age': 18, 'height': 186}
{'name': 'jerry', 'age': 20, 'height': 206}
{'height': 196, '__init__': <function Person.__init__ at 0x000002719C565AE8>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__module__': '__main__', '__doc__': None, 'age': 30, '__dict__': <attribute '__dict__' of 'Person' objects>}

是类的,也是这个类所有实例的,是实例的,就是实例自己的,通过类访问不到 

Person.weight = 70
print(Person.__dict__['weight'])
print(tom.weight)  # 可以通过搜索机制,自己字典没有就去类的字典找
print(tom.__dict__['weight'])  # 而这不行,是看自己的字典里有没有,没有KeyError

实例属性的查找顺序:

指的是实例使用 来访问属性,会先找自己的__dict__,如果没有,就通过属性__class__找到自己的类

再去类的__dict__中找

如果是使用__dict__[变量]访问变量,有就有,没有就不会去找类的

一般,类变量使用全大写来命名


装饰一个类:

def add_name(name):
    def wrapper(cls):
        cls.NAME = name
        return cls
    return wrapper


@add_name('jerry')
class Person:
    age = 123


print(Person.NAME)

类方法:

class Person:
    age = 123

    @classmethod
    def clsmtd(cls):
        print('{}.age = {}'.format(cls.__name__, cls.age))


Person.clsmtd()
a = Person()
a.clsmtd()  # a.__class__.clsmtd()
print(a.__class__)

1、在类定义中,使用@classmethod装饰器修饰的方法

2、必须至少有一个参数,且第一个参数留给了cls,cls指代调用者,就是类对象自身

3、cls这个标识符可以是任意合法名称,但是为了易读,请不要修改

4、通过cls可以直接操作类的属性,不可操作类的实例 

 

静态方法:

class Person:
    age = 123

    @staticmethod
    def staticmtd():
        print('static')


Person.staticmtd()
a = Person()
a.staticmtd()

1、在类定义中,使用@staticmethod装饰器修饰方法

2、调用时,不会隐式的传入参数,静态方法,只是表明这个方法属于这个名词空间,函数归在一起,方法组织管理

 

以上这些方法怎么调用?

class Person:
    def normal_method():
        print('normal')

    def method(self):
        print("{}'s method".format(self))

    @classmethod
    def class_method(cls):
        print('class = {0.__name__} ({0})'.format(cls))
        cls.HEIGHT = 176

    @staticmethod
    def staticmtd():
        print(Person.HEIGHT)


print(1, Person.normal_method())
# print(2, Person.method())   这个不行
# TypeError: method() missing 1 required positional argument: 'self'
print(3, Person.class_method())
print(4, Person.staticmtd())
print(Person.__dict__)
print('----------------')
tom = Person()
# print(1, tom.normal_method()) 这个不行
# TypeError: normal_method() takes 0 positional arguments but 1 was given
print(2, tom.method())
print(3, tom.class_method())
print(4, tom.staticmtd())



out:
normal
1 None
class = Person (<class '__main__.Person'>)
3 None
176
4 None
{'class_method': <classmethod object at 0x000001A1A65CA5C0>, 'method': <function Person.method at 0x000001A1A66E2048>, '__module__': '__main__', 'normal_method': <function Person.normal_method at 0x000001A1A65C5F28>, 'staticmtd': <staticmethod object at 0x000001A1A65CA7B8>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'HEIGHT': 176, '__dict__': <attribute '__dict__' of 'Person' objects>}
----------------
<__main__.Person object at 0x000001A1A65CA898>'s method
2 None
class = Person (<class '__main__.Person'>)
3 None
176
4 None

类几乎可以调用所有内部定义的方法,但调用普通方法时会报错,原因是第一个参数必须是实例

实例也几乎可以调用所有的方法,普通的函数调用一般不可能出现,因为不允许这么定义 

普通方法传入实例自身,静态方法和类方法需要找到实例的类

class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.age = age

    def growup(self, i=1):
        if 0 < i < 150:  # 控制逻辑
            self.age += i


p1 = Person('tom')
p1.growup(20)
print(p1.age)
p1.age = 160   # 超过了范围,并绕过了控制逻辑
print(p1.age)

out:
38
160

 上例,本来是想通过方法控制属性,但由于属性在外部可以访问,或者说可见,就可以直接绕过方法,

直接修改这个属性。

Python提供了私有属性可以解决这个问题

私有属性:使用双下划线开头的属性名

如下面例子:

class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age   # 私有变量

    def growup(self, incr=1):
        if 0 < incr < 150:
            self.__age += incr

    def getage(self):
        return self.__age


tom = Person('tom')
tom.growup(5)
print(tom.getage())  # 此时,外部已经访问不到__age,使用getage这个方法来获取
print(tom.__dict__)
print(tom._Person__age) # 这样找还是找的到的

out:
23
{'_Person__age': 23, 'name': 'tom'} # 其实就是改了个名字,所以外部找不到了
23

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值