[py]a python tutor

python设计哲学

Pythonic就是以Python的方式写出简洁优美的代码

Python本身没有任何机制阻止你干坏事,一切全靠自觉。

In [1]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

python语言特性

用一些特殊标识来约定(自觉遵守,不要求强制)
    常量定义: WEEKDAY = 8
    类中权限保护: 方法名前加 __
//变量

支持定义后不使用
支持重复声明定义
    a = 10
    a = 'm'

变量名和要避讳py关键字
In [1]: import keyword # python3.6.6

In [2]: keyword.kwlist
Out[2]:
['False',
 'None',
 'True',
 'and',
 'as',
 'assert',
 'break',
 'class',
 'continue',
 'def',
 'del',
 'elif',
 'else',
 'except',
 'finally',
 'for',
 'from',
 'global',
 'if',
 'import',
 'in',
 'is',
 'lambda',
 'nonlocal',
 'not',
 'or',
 'pass',
 'raise',
 'return',
 'try',
 'while',
 'with',
 'yield']

In [3]: len(keyword.kwlist)
Out[3]: 33

python3.8新增了async await关键字. 总共35个.
//函数

不支持重载
支持不定参数
支持返回多值

buildins里方法和类

// buildins.py里的函数(体现py面向过程)

abs
all
any
ascii
bin
callable
chr
compile
copyright
credits
delattr
dir         # 函数不带参数时,返回当前范围内的(变量/类型/对象)列表; 带参数(变量/类型/对象)时,返回参数的属性、方法列表。
divmod
eval
exec
exit
format
getattr
globals
hasattr
hash
help
hex
id          # cpython中取的是内存地址
input
isinstance
issubclass
iter
len
license
locals
max
min
next
oct
open
ord
pow
print
quit
repr
round
setattr
sorted   #冒泡排序/快排
sum
vars
__build_class__
__import__
// buildins.py里常见类(体现py面向对象)

class object:
class type(object)
    type(object_or_name, bases, dict)
    type(object) -> the object's type
    type(name, bases, dict) -> a new type

class int(object)
class bool(object)
class str(object)

class tuple(object)
class list(object)
class dict(object)

class map(object) //根据提供的函数对指定序列做映射.
class filter(object) //函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象, 如果要转换为列表

functools.reduce //函数会对参数序列中元素进行累计.


class enumerate(object):
class super(object):    # 通过子类调用父类方法, super(Zi, zi).show()

object中魔术方法

dir(object)类或实例 dir(people)普通类或实例 作用
__class__ __class__ -
__delattr__ __delattr__ -
__dir__ __dict__ -
__doc__ __dir__(多) 作用: dir(obj) == obj.__dir()
__eq__ __doc__ 作用: 返回类的注释
__format__ __eq__ -
__ge__ __format__ -
__getattribute__ __ge__ -
__gt__ __getattribute__ -
__hash__ __gt__ -
__init__ __hash__
干掉可哈希 hash == None 对象就不可哈希了。
__init_subclass__ __init__ -
__le__ __init_subclass__ 作用: 构造方法, 用于构造实例属性
参数: self
返回值: 无
类名() 会自动执行__init__()
__lt__ __le__ -
__ne__ __lt__ -
__new__ __module__(多) -
__reduce__ __ne__ -
__reduce_ex__ __new__ 实例化第一步, 开辟内存(new)
__repr__ __reduce__ -
__setattr__ __reduce_ex__ -
__sizeof__ __repr__ -
__str__ __setattr__ -
__subclasshook__ __sizeof__ sys.getsizeof调用该对象的__sizeof__方法,获取类型占字节数
23 __str__ 作用: 通常返回一个字符串,作为这个对象的描述信息
参数:self
返回值: str, 默认返回str(self)
- __subclasshook__ -
- __weakref__(多) -
1. 类名() 会自动执行__init__()
2. 对象() 会自动执行__call__()
3. 对象[key] 会自动执行__getitem__()
4. 对象[key] = value 会自动执行__setitem__()
5. del 对象[key] 会自动执行 __delitem__(),  如果显示声明__del__()
6. 对象+对象 会自动执行__add__()

7. with 对象 as 变量会自动执行__enter__ 和__exit__
8. 打印对象的时候 会自动执行__str__
9. 干掉可哈希 __hash__ == None 对象就不可哈希了。
// 创建对象的真正步骤:
首先, 在执行行类名()的时候. 系统会自动先执行行__new__()来开辟内存. 
此时新开辟出来的内存区域是空的. 
紧随其后, 系统自动调⽤用__init__()来完成对象的初始化⼯工作. 按照时间轴来算.
1. 加载类
2. 开辟内存(__new__)
3. 初始化(__init__)
4. 使⽤用对象⼲干xxxxxxxxx

类似的操作还有很多很多. 

python中int类数据的内存大小

dict()与__dict__

len() 与__len__

__len__,__getitem__,__setitem__,__delitem__
__getattr__,__setattr__
getattr,hasattr,setattr,delattr

object中默认魔术方法-分类

__new__
__init__
__str__
__repr__


__dir__
__doc__
__module__

__class__

__delattr__
__setattr__
__getattribute__

__dict__
__format__

__sizeof__
__eq__.    # is比较对象的id, == 比较对象的value. ==调用的是对象的__eq__
__ge__
__gt__
__le__
__lt__
__ne__

__hash__
__reduce__
__reduce_ex__
__init_subclass__
__subclasshook__
__weakref__

del内置函数

// del函数
当有变量保存了一个对象的引用时,此对象的引用计数就会加1;

当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)。

class Hero(object):

    # 初始化方法
    # 创建完对象后会自动被调用
    def __init__(self, name):
        print('__init__方法被调用')
        self.name = name

    # 当对象被删除时,会自动被调用
    def __del__(self):
        print("__del__方法被调用")
        print("%s 被 GM 干掉了..." % self.name)


# 创建对象
taidamier = Hero("泰达米尔")

# 删除对象
print("%d 被删除1次" % id(taidamier))
del(taidamier)


print("--" * 10)


gailun = Hero("盖伦")
gailun1 = gailun
gailun2 = gailun

print("%d 被删除1次" % id(gailun))
del(gailun)

print("%d 被删除1次" % id(gailun1))
del(gailun1)

print("%d 被删除1次" % id(gailun2))
del(gailun2)

高阶函数map reduce filter

1.map 用法

map() 会根据提供的函数对指定序列做映射.

第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表.

计算每一个元素的平方值:

my_list = [1, 2, 3, 4, 5]


def f(x):
    return x ** 2

result = map(f, my_list)
print(type(result), result, list(result))

输出结果:

<class 'map'> <map object at 0x000000C9729591D0> [1, 4, 9, 16, 25]

示例解释:

首字母大写:

my_list = ['smith', 'edward', 'john', 'obama', 'tom']


def f(x):
    return x[0].upper() + x[1:]


result = map(f, my_list)
print(list(result))

输出结果:

['Smith', 'Edward', 'John', 'Obama', 'Tom']

2. reduce 用法

reduce() 函数会对参数序列中元素进行累计.

函数将一个数据集合中的所有数据进行下列操作:

用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作.
得到的结果再与第三个数据用 function 函数运算, 最后得到一个结果.
计算列表中的累加和:

import functools

my_list = [1, 2, 3, 4, 5]


def f(x1, x2):
    return x1 + x2


result = functools.reduce(f, my_list)
print(result)

输出结果:

15

示例解释:

3. filter 用法

filter() 函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象, 如果要转换为列表, 可以使用 list() 来转换.

该接收两个参数, 第一个为函数, 第二个为序列, 序列的每个元素作为参数传递给函数进行判, 然后返回 True 或 False, 最后将返回 True 的元素放到新列表中.

过滤列表中的偶数:

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def f(x):
    return x % 2 == 0


result = filter(f, my_list)
print(list(result))

输出结果:

[2, 4, 6, 8, 10]

示例解释:

过滤列表中首字母为大写的单词:

my_list = ['edward', 'Smith', 'Obama', 'john', 'tom']


def f(x):
    return x[0].isupper()


result = filter(f, my_list)
print(list(result))

输出结果:

['Smith', 'Obama']

setattr内置函数

class People():
    name = "mm"


setattr(People, "name", "gg")  # setattr(x, 'y', v) is equivalent to ``x.y = v''
print(People.name)
# gg

type与isinstance

type获取变量类型

如果一个变量指向函数或者类,也可以用type()判断:

>>> type(abs)
<class 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>

但是type()函数返回的是什么类型呢?它返回对应的Class类型。

>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False

判断基本数据类型可以直接写int,str等,但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

isinstance判断继承

能用type()判断的基本类型也可以用isinstance()判断:

>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True

注: 总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。

Python中的类属性、实例属性与类方法、静态方法

定义一个类, 其实是定义一种类型.

把Person称为超类(super class),父类(parent class),基类(base class),把Student称为子类(subclass),扩展类(extended class)。

类方法

//使用类方法获取类属性

class people:
    country="china"
 
    @classmethod
    def getCountry(cls):
        return cls.country

p=people()
print(p.getCountry())       #实例对象调用类方法
print(people.getCountry())  #类对象调用类方法
//使用类方法设置类属性

class people:
    country="china"
 
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def setCountry(cls,country):
        cls.country=country
 
 
p=people()
print(p.getCountry())   #实例对象调用类方法
print(people.getCountry())  #类对象调用类方法
 
p.setCountry("Japan")
 
print(p.getCountry())
print(people.getCountry())

静态方法

不需要操作类中任何数据(类属性/实例属性)

class people3:
    country="china"
 
    @staticmethod
    def getCountry():
        return people3.country

p=people3()
print(p.getCountry())        #实例对象调用类方法
print(people3.getCountry())  #类对象调用类方法

//静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用

类属性的设置

# 如果在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,
# 会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且如果通过
# 实例对象引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性
class People:
    name = "mm"


p = People()
p.name = "gg"
People.name = "m1"
print(p.name)

//gg
class Animal:
    name="Panda"
 
print(Animal.name)  #类对象引用类属性
p=Animal()
print(p.name)       #实例对象引用类属性时,会产生一个同名的实例属性
p.name="dog"        #修改的只是实例属性的,不会影响到类属性
print(p.name)         #dog
print(Animal.name)    #panda
# 删除实例属性
del p.name
print(p.name)

为什么说Python是一门动态语言--Python的魅力

可以动态增删对象的属性和方法.

GIL锁子

GUIDO声明去掉GIL不容易

GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
Python使用多进程是可以利用多核的CPU资源的。

计算密集型: 进程
io密集型: 线程/协程。

01.py--->cpython/jpython --> 0101001

函数

// 函数不定长参数

def test(a, *args, **kwargs):
    print(a)
    print(args)
    print(kwargs)


test(1, 2, 3, 4, name="mm1", age=22)
# 1
# (2, 3, 4)
# {'name': 'mm1', 'age': 22}

//list展开运算

def test(a, *args):
    print(a)
    print(args)


arr = [1, 2, 3, 4]
test(*arr)
def test(a, *args, **kwargs):
    print(a)
    print(args)
    print(kwargs)


arr = [1, 2, 3, 4]
d = {
    "name": "mm1",
    "age": 22,
}
test(1, *arr, **d)
# 1
# (1, 2, 3, 4)
# {'name': 'mm1', 'age': 22}

python property 与get/set方法详解

作用1: 封装属性

//java中封装

public class Person {

    private int age;

    public Person(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
//python3中类似的写法, 显然不符合pythonic风格, 太麻烦类.
class Person(object):

    def __init__(self):
        self._age = None

    def get_age(self):
        return self._age

    def set_age(self,age):
        if(isinstance(age,str)):
            self._age = int(age)
        elif(isinstance(age,int)):
            self._age = age
// python3中更优雅的写法:
class Person(object):

    def __init__(self):
        self._age = None

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,age):
        if isinstance(age,str):
            self._age = int(age)
        elif isinstance(age,int):
            self._age = age

    @age.deleter
    def age(self):
        del self._age

p = Person()
p.age = "18"
print p.age #18
del p.age
print p.age #报错,AttributeError: 'Person' object has no attribute '_age'

作用2: 修饰计算属性

我们还可以用property来定义需要进行计算的字段。这些字段不会保存在对象中,只有当我们实际需要的时候才会完成真正计算。

class Person(object):

    def __init__(self):
        self._age = None

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,age):
        if isinstance(age,str):
            self._age = int(age)
        elif isinstance(age,int):
            self._age = age

    @property
    def height(self):
        return self.age * 10

p = Person()
p.age = ("18")
print p.height #180

pycharm中输入props即可自动生成(properties->live template->python)

约束子类必须实现父类的方法

class People:
    def to_internal_value(self, data):
        raise NotImplementedError('`to_internal_value()` must be implemented.')


class Student(People):
    pass


s = Student()
s.to_internal_value(123)
# NotImplementedError: `to_internal_value()` must be implemented.

类属性的意义

多个学生来自同一个学校, 学校名属性可以定义为类属性, 被共享.(静态属性)

浅谈python使用多态跟不用多态的区别

多态, 不同的 子类对象调用 相同的 父类方法,产生 不同的 执行结果,可以增加代码的外部 调用灵活度,
多态以 继承 和 重写 父类方法 为前提
多态是调用方法的技巧,不会影响到类的内部设计
下面就用一段简单的代码来看看多态的优点

首先,我们看一下没有多态的代码:

class ArmyDog(object):

    def bite_enemy(self):
        print('追击敌人')

class DrugDog(object):

    def track_drug(self):
        print('追查毒品')


class Person(object):

    def work_with_army(self, dog):
        dog.bite_enemy()

    def work_with_drug(self, dog):
        dog.track_drug()


p = Person()
p.work_with_army(ArmyDog())
p.work_with_drug(DrugDog())

这样可以看出,如果添加一个类,继承Dog,代码的增加就很麻烦。

下面我们来看一下有多态的情形:

class Dog(object):
    def work(self):
        pass


class ArmyDog(Dog):
    def work(self):
        print('追击敌人')


class DrugDog(Dog):
    def work(self):
        print('追查毒品')


class Person(object):
    def work_with_dog(self, dog):  # 只要能接收父类对象,就能接收子类对象
        dog.work()  # 只要父类对象能工作,子类对象就能工作。并且不同子类会产生不同的执行效果。


p = Person()
p.work_with_dog(ArmyDog())
p.work_with_dog(DrugDog())

这样一来,添加一个类就显得很方便了。

[Python3]抽象类

#定义抽象方法,无需实现功能
#子类继承抽象类,但是必须定义read和write方法

检测闭包__closure__

python的特有机制global和nonelocal

获取, 一直追到上级作用域
修改, 本作用域没有, 上级作用域有, 也没法直接修改, 需要global声明一下,我要修改全局了,才能修改

闭包. 返回None就不是闭包

def func1():
	name = "mm"
	def func2():
		print(name) # 闭包
	func2()
	print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at0x10c3fc650>,)
func1()

判断可迭代对象__iter__

链表的结构使用迭代效率更高.

可迭代对象

dir(obj)
在打印结果中. 寻找__iter__ 如果能找到. 那么这个类的对象就是⼀一个可迭代对象

str,list, tuple, dict, set 都有这个属性

l = [1,2,3]
l_iter = l.__iter__()

from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable)) #True
print(isinstance(l,Iterator)) #False
print(isinstance(l_iter,Iterator)) #True
print(isinstance(l_iter,Iterable)) #True
s = "我爱北京天安门"
c = s.__iter__() # 获取迭代器
print(c.__next__()) # 使用迭代器进行迭代. 获取一个元素 我
print(c.__next__()) # 爱
print(c.__next__()) # 北
print(c.__next__()) # 京
print(c.__next__()) # 天
print(c.__next__()) # 安
print(c.__next__()) # 门
print(c.__next__()) # StopIteration

for循环的机制

for i in [1,2,3]:
	print(i)

使用while循环+迭代器来模拟for循环

lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
	try:
		i = lst_iter.__next__()
		print(i)
	except StopIteration:
		break

总结

Iterable: 可迭代对象. 内部包含__iter__()函数
Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().

迭代器的特点:

  1. 节省内存.
  2. 惰性机制
  3. 不能反复, 只能向下执行

我们可以把要迭代的内容当成子弹. 然后呢. 获取到迭代器__iter__(), 就把子弹都装在弹夹中. 然后发射就是__next__()把每一个子弹(元素)打出来. 也就是说, for循环的时候.
一开始的时候是__iter__()来获取迭代器. 后面每次获取元素都是通过__next__()来完成的.
当程序遇到StopIteration将结束循环.

java中静态和非静态的区别


Java提高篇——JVM加载class文件的原理机制

1.装载: 类加载器 查找和导入class文件;
  通过new显式加载
  通过class.forname等反射机制隐式(运行时加载)加载.

2.连接:

      (1)检查:检查载入的class文件数据的正确性;

      (2)准备:为类的静态变量分配存储空间;

      (3)解析:将符号引用转换成直接引用(这一步是可选的)

3.初始化:初始化静态变量,静态代码块。

      这样的过程在程序调用类的静态成员的时候开始执行,所以静态方法main()才会成为一般程序的入口方法。类的构造器也会引发该动作。

Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序

  • static关键字特点:
    随着类的加载而加载
    优先于对象存在
    被类的所有对象共享
    可以通过类名调用
    注:
    静态方法中没有this和super关键字
    静态方法只能访问静态成员变量和静态成员方法

  • 静态 vs 非静态

## 内存出现的实现不同:
静态变量随着类的加载而加载,随着类的消失而消失.
非静态变量随着对象的创建而存在,随着对象的消失而消失.


## 所属不同
静态变量属于类,也称为类变量
非静态变量属于对象,所以也称为实例变量.

## 内存中位置不同
静态变量存储于方法区的静态区
非静态变量存储于堆内存

## 调用不同:

// 静态属性随着类的加载而加载
       静态属性    非静态属性
类     yes        no
实例   yes        yes

// 静态方法随着类的加载而加载
       静态方法    非静态方法
类     yes        no
实例   yes        yes

注: 静态方法内
    不能使用self,或super关键字.
    不能修改非静态属性(因为他们生命周期比实例早)
  • 面向对象的工具类使用静态.

类方法和静态方法区别

python面向对象

类方法用在模拟java定义多个构造函数的情况。

由于python类中只能有一个初始化方法,不能按照不同的情况初始化类。

参考django https://docs.djangoproject.com/en/1.9/ref/models/instances/ 请看下面的代码。

# coding:utf-8
class Book(object):
 
    def __init__(self, title):
        self.title = title
 
    @classmethod
    def class_method_create(cls, title):
        book = cls(title=title)
        return book
 
    @staticmethod
    def static_method_create(title):
        book= Book(title)
        return book
 
book1 = Book("use instance_method_create book instance")
book2 = Book.class_method_create("use class_method_create book instance")
book3 = Book.static_method_create("use static_method_create book instance")
print(book1.title)
print(book2.title)
print(book3.title)
use instance_method_create book instance
use class_method_create book instance
use static_method_create book instance

Process finished with exit code 0

特别说明,静态方法也可以实现上面功能,当静态方法每次都要写上类的名字,不方便。

继承类中的区别

从下面代码可以看出,如果子类继承父类的方法,子类覆盖了父类的静态方法,
子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。

子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。

posted @ 2020-02-22 11:14  mmaotai  阅读(278)  评论(0编辑  收藏  举报