变量和注释

1.变量

在编写变量尽量要让其清晰只给,让人清除搞清楚代码的意图

下方两段代码作用完全一样,但第二段代码是不是更容易让人理解

  1. value = s.strip()
  2.  
  3. username = input_string.strip()

1.1变量的基础知识

1.1.1变量的交换

作为一门动态语言,我们不仅可以无需预先声明变量类型直接赋值

同时还可以在一行内操作多个变量,比如交换

  1. parent, child = "father", "son"
  2. parent, child = child, parent
  3. print(parent)#son
1.1.2变量解包
  1. fruit = ["red apple","green apple","orange"]
  2. *apple, orange =fruit
  3. print(apple) #['red apple', 'green apple']
1.1.3变量用单下划线命名

它常作为一个无意义的占位符出现在赋值语句中,例如你想在解包时候忽略某些变量

  1. fruit = ["red apple","green apple","orange"]
  2. *_, orange =fruit #这里的_就意味着这个变量后续不太会使用的,可以忽略的
  3. print(orange) #orange
1.1.4给变量注明类型

虽然Pyhton无需声明变量,声明了变量也无法起到校验的作用

但我们还是需要去注明类型来提高我们代码的可读性

最常见的做法是写函数文档,把参数类型与说明写在函数文档内

  1. def hello_world(items):
  2. """
  3. 这是进入编程大门的入口
  4. :param items: 待入门的对象
  5. :type items: 包含字符串的列表,[string,...]
  6. """
  7. pass

或者添加类型注解

  1. from typing import List
  2.  
  3. def hello_world(items: List[str]):
  4. """
  5. 这是进入编程大门的入口
  6. """

2.数值和字符串

2.1数值

2.1.1浮点数的精度问题
  1. print(0.1+0.2)#0.30000000000000004
  2. 为了解决上述的精度问题我们可以用decimal这个内置函数
  3. from decimal import Decimal
  4. print(Decimal('0.1')+Decimal('0.2'))#必须用字符串表示数字

2.2字符串

2.2.1拼接多个字符串

最常见的做法是创建一个空列表,然后把需要拼接的字符串都放进列表中

最后使用str.join来拼接

除此之外也可以通过+号来拼接

3容器类型

最常见的内置容器类型有四种:列表、元组、字典、集合

3.1具名元祖

元组经常用来存放结构化数据,但只能通过数字来访问元组成员其实特别不方便

  1. 初始化具名函数
  2. 可以通过数字索引来访问
  3. 也可以通过名称来访问
  1. from collections import namedtuple
  2. FruitColor = namedtuple('FruitColor','apple,orange')
  3. fruitColor = FruitColor("RED","GREEN")
  4. print(fruitColor[0])#RED
  5. print(fruitColor.apple)#RED

Python3.6以后我们还可以用类型注解语法和typing.NameTuple来定义具名函数

  1. from typing import NamedTuple
  2. class FruitColor(NamedTuple):
  3. apple: str
  4. orange: str
  5.  
  6. fruitColor = FruitColor("RED","GREEN")
  7. print(fruitColor[0])
  8. print(fruitColor.apple)

3.2访问不存在的字典键

当用不存在的键访问字典内容时,程序会抛出KeyError异常

通常的做法:读取内容前先做一次条件判断,只有判断通过的情况下才继续执行其他操作

  1. if "first" in example:
  2. num = example["first"]
  3. else:
  4. num = 0

或者

  1. try:
  2. num = example["first"]
  3. except KeyError:
  4. num = 0

如果只是“提供默认值的读取操作”,其实可以直接使用字典的.get()方法

  1. #dict.get(key, default)方法接收一个default参数
  2. example.get("first",0)

3.3使用setdefault取值并修改

比如我们有一个字典,这个字典内我们不知道有没有这个键

  1. example = {"first":[1],"second":[2]}
    try:
  2. example["third"].append(3)
  3. except KeyError:
  4. example["third"] = [3]

除了上述写法还有一个更合适的写法

调用dict.setdefault(key, default)会产生两种结果:

当key不存在时,该方法会把default值写入字典的key位置,并返回该值;

假如key已经存在,该方法就会直接返回它在字典中的对应值

  1. example.setdefault("third",[]).append(3)

3.4认识字典的有序性

在Python 3.6版本以前,几乎所有开发者都遵从一条常识:“Python的字典是无序的。

”这里的无序指的是:当你按照某种顺序把内容存进字典后,就永远没法按照原顺序把它取出来了。

这种无序现象,是由字典的底层实现所决定的

Python里的字典在底层使用了哈希表(hash table)数据结构。当你往字典里存放一对key: value时,Python会先通过哈希算法计算出key的哈希值——一个整型数字;然后根据这个哈希值,决定数据在表里的具体位置

因此,最初的内容插入顺序,在这个哈希过程中被自然丢掉了,字典里的内容顺序变得仅与哈希值相关,与写入顺序无关

字典变为有序只是作为3.6版本的“隐藏特性”存在。但到了3.7版本,它已经彻底成了语言规范的一部分

4.条件分支

4.1分支基础注意事项

4.1.1不要显式地和布尔值做比较
  1. #不推荐的写法
  2. if example.is_deleted() == True:
  3.  
  4. # 推荐写法
  5. if example.is_deleted():
4.1.2省略0值判断

在if分支里时,解释器会主动对它进行“真值测试”,也就是调用bool()函数获取它的布尔值

  1. if containers_count == 0:
  2. pass
  3. if fruits_list != []:
  4. pass

所以我们可以把代码改成如下:

  1. if not containers_count:
  2. pass
  3. if fruits_list:
  4. pass
4.1.3三元表达式

一种浓缩版的条件分支——三元表达式

  1. #语法:
  2. # true_value if <expression> else false_value
4.1.4修改对象的布尔值
  1. from typing import List
  2. class Length:
  3. def __init__(self,items: List[str]):
  4. self.items = items
  5.  
  6. lengthList = Length(["2","3"])
  7.  
  8. if len(lengthList.items) > 0 :
  9. pass

只要给UserCollection类实现__len__魔法方法,实际上就是为它实现了Python世界的长度协议

  1. from typing import List
  2. class Length:
  3. def __init__(self,items: List[str]):
  4. self.items = items
  5.  
  6. def __len__(self):
  7. return len(self.items)

或者可以在类中实现__bool__

  1. from typing import List
  2. class Length:
  3. def __init__(self,items: List[str]):
  4. self.items = items
  5.  
  6. def __bool__(self):
  7. return len(self.items)>2
  8.  
  9. lengthList = Length(["2","3"])
  10.  
  11. print(bool(lengthList)) #Fales

注:

假如一个类同时定义了__len__和__bool__两个方法,解释器会优先使用__bool__方法的执行结果

4.2优化分支代码

4.2.1优化枚举代码
  1. class Movie:
  2. """电影对象数据类"""
  3. @property
  4. def rank(self):
  5. """按照评分对电影分级:
  6.  
  7. - S: 8.5 分及以上
  8. - A:8 ~ 8.5 分
  9. - B:7 ~ 8 分
  10. - C:6 ~ 7 分
  11. - D:6 分以下
  12. """
  13. rating_num = float(self.rating)
  14. if rating_num >= 8.5:
  15. return 'S'
  16. elif rating_num >= 8:
  17. return 'A'
  18. elif rating_num >= 7:
  19. return 'B'
  20. elif rating_num >= 6:
  21. return 'C'
  22. else:
  23. return 'D'

这就是一个普通的枚举代码,根据电影评分给予不同的分级,但是代码冗余

使用二分法模块进行优化

  1. import bisect
  2. @property
  3. def rank(self):
  4. # 已经排好序的评级分界点
  5. breakpoints = (6, 7, 8, 8.5)
  6. # 各评分区间级别名
  7. grades = ('D', 'C', 'B', 'A', 'S')
  8. index = bisect.bisect(breakpoints, float(self.rating))
  9. return grades[index]
4.2.2 使用字典优化分支
  1. def get_sorted_movies(movies, sorting_type):
  2. if sorting_type == 'name':
  3. sorted_movies = sorted(movies, key=lambda movie: movie.name.lower())
  4. elif sorting_type == 'rating':
  5. sorted_movies = sorted(
  6. movies, key=lambda movie: float(movie.rating), reverse=True
  7. )
  8. elif sorting_type == 'year':
  9. sorted_movies = sorted(
  10. movies, key=lambda movie: movie.year, reverse=True
  11. )
  12. elif sorting_type == 'random':
  13. sorted_movies = sorted(movies, key=lambda movie: random.random())
  14. else:
  15. raise RuntimeError(f'Unknown sorting type: {sorting_type}')
  16. return sorted_movies

我们发现每一个分支都基本一样:

都是对sorting_type做等值判断(sorting_type == 'name')

逻辑也大同小异——都是调用sorted()函数,只是key和reverse参数略有不同

所以我们考虑用字典去优化:

  1. sorting_algos = {
  2. # sorting_type: (key_func, reverse)
  3. 'name': (lambda movie: movie.name.lower(), False),
  4. 'rating': (lambda movie: float(movie.rating), True),
  5. 'year': (lambda movie: movie.year, True),
  6. 'random': (lambda movie: random.random(), False),
  7. }

4.3建议

4.3.1尽量避免多层嵌套

这些多层嵌套可以用一个简单的技巧来优化——“提前返回”。

“提前返回”指的是:当你在编写分支时,首先找到那些会中断执行的条件,把它们移到函数的最前面,然后在分支里直接使用return或raise结束执行。

4.3.2别写太复杂的表达式

如果表达式很长很复杂:

我们需要对条件表达式进行简化,把它们封装成函数或者对应的类方法,这样才能提升分支代码的可读性

4.3.3使用德摩根定律

简单来说,“德摩根定律”告诉了我们这么一件事:not A or not B等价于not (A and B)。

  1. if not A or not B:
  2. pass
  3. #可以改写成
  4. if not (A and B):
  5. pass

这样写少了一个not变成更容易理解

4.3.4使用all() any()函数构建条件表达式

· all(iterable):仅当iterable中所有成员的布尔值都为真时返回True,否则返回False。

· any(iterable):只要iterable中任何一个成员的布尔值为真就返回True,否则返回False。

  1. def all_numbers_gt_10(numbers):
  2. """仅当序列中所有数字都大于10 时,返回 True"""
  3. if not numbers:
  4. return False
  5.  
  6. for n in numbers:
  7. if n <= 10:
  8. return False
  9. return True
  10.  
  11. #改写后
  12. def all_numbers_gt_10_2(numbers):
  13. return bool(numbers) and all(n > 10 for n in numbers)
4.3.5 or的短路特性
  1. #or最有趣的地方是它的“短路求值”特性。比如在下面的例子里,1 / 0永远不会被执行,也就意味着不会抛出ZeroDivisionError异常
  2. True or (1 / 0)

所以我们利用这个特性可以简化一些分支

  1. context = {}
  2. # 仅当 extra_context 不为 None 时,将其追加进 context 中
  3. if extra_context:
  4. context.update(extra_context)
  5.  
  6. #优化后
  7. context.update(extra_context or {})

5异常处理

5.1获取原谅比许可更简单

在Python世界里,EAFP指不做任何事前检查,直接执行操作,但在外层用try来捕获可能发生的异常。

  1. def changeInt(value):
  2. """Try to convert the input to an integer"""
  3. try:
  4. return int(value)
  5. except TypeError:
  6. print(f'type error:{type(value)} is invalid')
  7. except ValueError:
  8. print(f'value error:{value} is invalid')
  9. finally:
  10. print('function completed')
5.1.1把最小的报错更精确的except放在最前面

如果把最大的报错放在最前面会导致所有的报错都报的同一个异常,其他都不会被触发

5.1.2使用else注意点
  1. try:
  2. oneBranch()
  3. except Exception as e:
  4. print("error")
  5. else:
  6. print("branch succeeded")
  • 异常捕获语句里的else表示:仅当try语句块里没抛出任何异常时,才执行else分支下的内容,效果就像在try最后增加一个标记变量一样
  • 和finally语句不同,假如程序在执行try代码块时碰到了return或break等跳转语句,中断了本次异常捕获,那么即便代码没抛出任何异常,else分支内的逻辑也不会被执行。
5.1.3使用空raise语句

当一个空raise语句出现在except块里时,它会原封不动地重新抛出当前异常

  1. try:
  2. oneBranch()
  3. except Exception as e:
  4. print("error")
  5. raise
  6. else:
  7. print("branch succeeded")
5.1.4使用上下文管理器

有一个关键字和异常处理也有着密切的关系,它就是with

with是一个神奇的关键字,它可以在代码中开辟一段由它管理的上下文,并控制程序在进入和退出这段上下文时的行为。

比如在上面的代码里,这段上下文所附加的主要行为就是:进入时打开某个文件并返回文件对象,退出时关闭该文件对象。

  1. class DummyContext:
  2. def __init__(self, name):
  3. self.name = name
  4.  
  5. def __enter__(self):
  6. #enter会在进入管理器被调用
  7. #返回接口
  8. return f'{self.name}'
  9.  
  10. def __exit__(self, exc_type, exc_val, exc_tb):
  11. #退出会被调用
  12. print('Exiting DummyContext')
  13. return False
  1. with DummyContext('HelloWorld') as name:
  2. print(f'Name:{name}')
  3.  
  4. #Name:HelloWorld
  5. #Exiting DummyContext

上下文管理器功能强大、用处很多,其中最常见的用处之一,就是简化异常处理工作

正如上方5.1的例子我们用with来简化finally

  1. def changeInt(value):
  2. """Try to convert the input to an integer"""
  3. with DummyContext():
  4. try:
  5. return int(value)
  6. except TypeError:
  7. print(f'type error:{type(value)} is invalid')
  8. except ValueError:
  9. print(f'value error:{value} is invalid')
  10.  
  11. class DummyContext:
  12. def __enter__(self):
  13. #enter会在进入管理器被调用
  14. #返回接口
  15. return True
  16.  
  17. def __exit__(self, exc_type, exc_val, exc_tb):
  18. #退出会被调用
  19. print('function completed')
  20. return False
  21.  
  22. print(changeInt(3))
  23. #function completed
  24. #3
5.1.5使用with用于忽略异常
  1. try:
  2. func()
  3. except :
  4. pass

虽然这样的代码很简单,但没法复用。当项目中有很多地方要忽略这类异常时,这些try/except语句就会分布在各个角落,看上去非常凌乱。

  1. class DummyContext:
  2. def __enter__(self):
  3. #enter会在进入管理器被调用
  4. #返回接口
  5. pass
  6.  
  7. def __exit__(self, exc_type, exc_val, exc_tb):
  8. #退出会被调用
  9. if exc_type == NameError:
  10. return True
  11. return False
  12.  
  13. with DummyContext() as c:
  14. func()

当你想忽略NameError异常时,只要把代码用with语句包裹起来即可

在代码执行时,假如with管辖的上下文内没有抛出任何异常,那么当解释器触发__exit__方法时,上面的三个参数值都是None;

但如果有异常抛出,这三个参数就会变成该异常的具体内容。

(1) exc_type:异常的类型。

(2) exc_value:异常对象。

(3) traceback:错误的堆栈对象。

此时,程序的行为取决于__exit__方法的返回值。如果__exit__返回了True,那么这个异常就会被当前的with语句压制住,不再继续抛出,达到“忽略异常”的效果;如果__exit__返回了False,那这个异常就会被正常抛出,交由调用方处理。

5.1.6使用contextmanager装饰器

虽然上下文管理器很好用,但定义一个符合协议的管理器对象其实挺麻烦的——得首先创建一个类,然后实现好几个魔法方法。

为了简化这部分工作,Python提供了一个非常好用的工具:@contextmanager装饰器

  1. from contextlib import contextmanager
  2.  
  3. @contextmanager
  4. def create_conn_obj(host, port, timeout=None):
  5. """创建连接对象,并在退出上下文时自动关闭"""
  6. conn = create_conn()
  7. try:
  8. yield conn
  9. finally:
  10. conn.close()

以yield关键字为界,yield前的逻辑会在进入管理器时执行(类似于__enter__),yield后的逻辑会在退出管理器时执行(类似于__exit__)

如果要在上下文管理器内处理异常,必须用try语句块包裹yield语句在日常工作中,我们用到的大多数上下文管理器,可以直接通过“生成器函数+@contextmanager”的方式来定义,这比创建一个符合协议的类要简单得多。

6循环和可迭代对象

在编写for循环时,不是所有对象都可以用作循环主体——只有那些可迭代(iterable)对象才行

说到可迭代对象,你最先想到的肯定是那些内置类型,比如字符串、生成器以及第3章介绍的所有容器类型,等等。

6.1iter()与next()的内置函数

当你使用for循环遍历某个可迭代对象时,其实是先调用了iter()拿到它的迭代器,然后不断地用next()从迭代器中获取值。

所以我们可以自己实现迭代器起到循环效果

  1. intList = [1,2,3,4]
  2.  
  3. num = iter(intList)
  4. while True:
  5. try:
  6. _int = next(num)
  7. print(_int)
  8. except StopIteration:
  9. break

6.2自定义迭代器

  1. class Range7:
  2. #生产一个包含7或者可以被7整除
  3. def __init__(self,start,end):
  4. self.start = start
  5. self.end = end
  6. #当前位置
  7. self.current = start
  8. #__iter__:调用iter()时触发,迭代器对象总是返回自身。
  9. def __iter__(self):
  10. return self
  11. # __next__:调用next()时触发,通过return来返回结果
  12. # 没有更多内容就抛出StopIteration异常,会在迭代过程中多次触发
  13. def __next__(self):
  14. while True:
  15. if self.current >= self.end:
  16. raise StopIteration
  17. if self.num_is_vaild(self.current):
  18. ret = self.current
  19. self.current += 1
  20. return ret
  21. self.current += 1
  22.  
  23. def num_is_vaild(self,num):
  24. #判断数字是否满足
  25. if not num :
  26. return False
  27. return num % 7 ==0 or '7' in str(num)
  28.  
  29. r = Range7(0,20)
  30. for num in r:
  31. print(num)

6.3区分迭代器与可迭代对象

一个合法的迭代器,必须同时实现__iter__和__next__两个魔法方法。

可迭代对象只需要实现__iter__方法,不一定得实现__next__方法。

  1. class Range7:
  2. def __init__(self,start,end):
  3. self.start = start
  4. self.end = end
  5.  
  6. def __iter__(self):
  7. #返回一个新的迭代器对象
  8. return Range7Iterator(self)
  9.  
  10. class Range7Iterator:
  11. #生产一个包含7或者可以被7整除
  12. def __init__(self,range_obj):
  13. self.end = range_obj.end
  14. self.start = range_obj.start
  15. #当前位置
  16. self.current = range_obj.start
  17. #__iter__:调用iter()时触发,迭代器对象总是返回自身。
  18. def __iter__(self):
  19. return self
  20. # __next__:调用next()时触发,通过return来返回结果
  21. # 没有更多内容就抛出StopIteration异常,会在迭代过程中多次触发
  22. def __next__(self):
  23. while True:
  24. if self.current >= self.end:
  25. raise StopIteration
  26. if self.num_is_vaild(self.current):
  27. ret = self.current
  28. self.current += 1
  29. return ret
  30. self.current += 1
  31.  
  32. def num_is_vaild(self,num):
  33. #判断数字是否满足
  34. if not num :
  35. return False
  36. return num % 7 ==0 or '7' in str(num)
  37.  
  38. r = Range7(0,20)
  39. print(tuple(r),1)
  40. print(tuple(r),2)

6.4生成器是迭代器

生成器还是一种简化的迭代器实现,使用它可以大大降低实现传统迭代器的编码成本。

因此在平时,我们基本不需要通过__iter__和__next__来实现迭代器,只要写上几个yield就行。

还是用上面的例子。我们用生成器来简化代码

  1. def isRang7(num: int):
  2.  
  3. return True if num !=0 and (num % 7 ==0 or '7' in str(num)) else False
  4.  
  5. def rang7(start: int, end: int):
  6. num = start
  7. while num < end :
  8. if isRang7(num):
  9. yield num
  10. num += 1

6.5使用itertools模块

看下面这个例子我们如何简化

  1. def find_twelve(num_list1, num_list2, num_list3):
  2. """从3 个数字列表中,寻找是否存在和为 12 的3 个数"""
  3. for num1 in num_list1:
  4. for num2 in num_list2:
  5. for num3 in num_list3:
  6. if num1 + num2 + num3 == 12:
  7. return num1, num2, num3

我们可以使用product()函数来优化它。product()接收多个可迭代对象作为参数,然后根据它们的笛卡儿积不断生成结果

  1. from itertools import product
  2. print(list(product([1,2],[3,4])))#[(1, 3), (1, 4), (2, 3), (2, 4)]
  1. from itertools import product
  2. def find_twelve_v2(num_list1, num_list2, num_list3):
  3. for num1, num2, num3 in product(num_list1, num_list2, num_list3):
  4. if num1 + num2 + num3 == 12:
  5. return num1, num2, num3

相比之前,新函数只用了一层for循环就完成了任务,代码变得更精练了。

7.函数

7.1常用函数模块

7.1.1functools.partial

functools是一个专门用来处理函数的内置模块,其中有十几个和函数相关的有用工具

  1. def multiply(x, y):
  2. return x * y
  3. #假设我们有很多地方需要调用上面这个函数
  4. #result = multiply(2, value)
  5. #val = multiply(2, number)
  6. #这些代码有一个共同的特点,这些代码有一个共同的特点
  7. #为了简化代码
  8. def double(value):
  9. # 返回 multiply 函数调用结果
  10. return multiply(2, value)
  11. # 调用代码变得更简单
  12. # result = double(value)
  13. # val = double(number)

针对这类场景,我们其实不需要像前面一样,用def去完全定义一个新函数——直接使用functools模块提供的高阶函数partial()就行。

  1. def multiply(x, y):
  2. return x * y
  3.  
  4. import functools
  5. double = functools.partial(multiply,2)
  6. print(double(3))#6
7.1.2functools.lru_cache()

为了提高效率,给这类慢函数加上缓存是比较常见的做法。

lru即“最近最少使用”(least recently used,LRU)算法丢掉旧缓存,释放内存

下面模拟一个慢函数

  1. import time
  2. from functools import lru_cache
  3. @lru_cache(maxsize=None)
  4. def slow_func():
  5. time.sleep(10)
  6. return 1

第一次缓存没有命中,耗时比较长

第二个调用相同函数,就不会触发函数内部逻辑,结果直接返回

在使用lru_cache()装饰器时,可以传入一个可选的maxsize参数,该参数代表当前函数最多可以保存多少个缓存结果。

默认情况下,maxsize的值为128。如果你把maxsize设置为None,函数就会保存每一个执行结果,不再剔除任何旧缓存。这时如果被缓存的内容太多,就会有占用过多内存的风险。

让Python更优雅更易读(第一集)的更多相关文章

  1. 让Python更优雅更易读(第二集)

    友情链接 让Python更优雅更易读(第一集) 1.装饰器 1.1装饰器特别适合用来实现以下功能 运行时校验:在执行阶段进行特定校验,当校验通不过时终止执行. 适合原因:装饰器可以方便地在函数执行前介 ...

  2. Karmada v1.3:更优雅 更精准 更高效

    摘要:最新发布的1.3版本中,Karmada重新设计了应用跨集群故障迁移功能,实现了基于污点的故障驱逐机制,并提供平滑的故障迁移过程,可以有效保障服务迁移过程的连续性(不断服). 本文分享自华为云社区 ...

  3. Selenium 2自动化测试实战36(更易读的测试报告)

    一.更易读的测试报告 1.知识点:python的注释. 1.一种叫comment,为普通的注释2.另一种叫doc string,用于函数,类和方法的描述.在类或方法的下方,通过三引号("&q ...

  4. 如何让code变得更易读

    从开始编码到现在,从没有意识去如何去写出更加规范,更加易读的代码,只是按照需求将某一功能进行实现.下面是最近在网上搜索查看的一些通用的知识点,做一记录. 单一抽象层次 单一抽象层次是指一个函数或者方法 ...

  5. git rebase VS git merge? 更优雅的 git 合并方式值得拥有

    写在前面 如果你不能很好的应用 Git,那么这里为你提供一个非常棒的 Git 在线练习工具 Git Online ,你可以更直观的看到你所使用的命令会产生什么效果 另外,你在使用 Git 合并分支时只 ...

  6. MySQL root密码忘记,原来还有更优雅的解法!

    一直以来,对于MySQL root密码的忘记,以为只有一种解法-skip-grant-tables. 问了下群里的大咖,第一反应也是skip-grant-tables.通过搜索引擎简单搜索了下,无论是 ...

  7. CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅

    首页   登录注册         CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅 阅读 8113 收藏 927 2017-09-26 原文链接:github.com 腾讯云容器服务CSS,立 ...

  8. 让 Java 中 if else 更优雅的几个小技巧

    对于一个高级 crud 工程师‍而言,if else 是写代码时使用频率最高的关键词之一,然而有时过多的 if else 会让我们优雅的 crud 代码显得不那么优雅,并且感到脑壳疼

  9. 少年,是时候换种更优雅的方式部署你的php代码了

    让我们来回忆下上次你是怎么发布你的代码的: 1. 先把线上的代码用ftp备份下来 2. 上传修改了的文件 3. 测试一下功能是否正常 4. 网站500了,赶紧用备份替换回去 5. 替换错了/替换漏了 ...

随机推荐

  1. Vue项目中的接口进阶使用

    创建services文件夹 1.文件夹apis.index.request的三个文件. 2.apis文件放接口 export const apis = { checkDeviceNo: '/api/c ...

  2. Python模块Ⅱ

    Python模块2 part3 模块的分类: 内置模块200种左右:python自带的模块,time os sys hashlib等 第三方模块6000种左右:需要pip install beauti ...

  3. 微信小程序开发 记录

    采坑了 微信小程序--TabBar不出现的一种原因 学习微信小程序中,遇到底部的TabBar不出现的问题.经过多番尝试,终于解决问题.在此记录问题产生的原因和对策.下面先描述错误现象,接着指出错误原因 ...

  4. vue 的个人学习小笔记

    一.vite2.0+vue3.0+ts 创建.配置 个人公众号文章地址 个人github仓库地址 1.Vite 创建 vue3 项目: 1.1.npm 常用命令 1.npm 查看版本号 npm vie ...

  5. Hadoop入门学习笔记(一)

    Week2 学习笔记 Hadoop核心组件 Hadoop HDFS(分布式文件存储系统):解决海量数据存储 Hadoop YARN(集群资源管理和任务调度框架):解决资源任务调度 Hadoop Map ...

  6. Spring AOP快速使用教程

    ​ Spring是方法级别的AOP框架,我们主要也是以某个类的某个方法作为连接点,用动态代理的理论来说,就是要拦截哪个方法织入对应的AOP通知.为了更方便的测试我们首先创建一个接口 public in ...

  7. python生产exe文件yi以及解释器配置等

    原文链接:https://blog.csdn.net/weixin_42691768/article/details/81044666 https://www.cnblogs.com/paulwhw/ ...

  8. JZOJ5384. 【NOIP2017提高A组模拟9.23】四维世界

    题目 Description 众所周知,我们常感受的世界是三维的. Polycarp突然对四维空间产生了兴趣,他想对四维空间进行一些研究.但是在此之前,他必须先对三维世界了解透彻. 于是Polycar ...

  9. VMware Workstation 虚拟机安装教程

    一.介绍篇 VMware Workstation 16 Pro是VMware(威睿公司)于2021年最新发布的一代虚拟机软件,软件的中文名是"VMware 工作站 16 专业版". ...

  10. Django——表单

    一.前言 看了下教程,以为表单很简单呢,结果搞了一两个钟才弄懂,哈哈哈,所以说不要小瞧每一件事. 先说明下HTTP请求: HTTP协议以"请求-回复"的方式工作.客户发送请求时,可 ...