首页 文章 精选 留言 我的

精选列表

搜索[Harness工程],共10000篇文章
优秀的个人博客,低调大师

Java工程师如何写出高效代码?

1.常量&变量 1.1.直接赋值常量值,禁止声明新对象 直接赋值常量值,只是创建了一个对象引用,而这个对象引用指向常量值。 反例:Long i = new Long(1L);String s = new String("abc"); 正例:Long i = 1L;String s = "abc"; 1.2.当成员变量值无需改变时,尽量定义为静态常量 在类的每个对象实例中,每个成员变量都有一份副本,而成员静态常量只有一份实例。 反例:public class HttpConnection { private final long timeout = 5L; ... } 正例:public class HttpConnection { private static final long TIMEOUT = 5L; ... } 1.3.尽量使用基本数据类

优秀的个人博客,低调大师

Java工程师该如何编写高效代码?

阿里妹导读:世界上只有两种物质:高效率和低效率;世界上只有两种人:高效率的人和低效率的人。——萧伯纳同理,世界上只有两种代码:高效代码和低效代码;世界上只有两种人:编写高效代码的人和编写低效代码的人。如何编写高效代码,是每个研发团队都面临的一个重大问题。本文作者根据实际经验,查阅了大量资料,总结了"Java高效代码50例",让每一个Java程序员都能编写出"高效代码"。 1.常量&变量 1.1.直接赋值常量值,禁止声明新对象 直接赋值常量值,只是创建了一个对象引用,而这个对象引用指向常量值; 反例: Long i = new Long(1L); String s = new String("abc"); 正例: Long i = 1L; String s = "abc"; 1.2.当成员变量值无需改变时,尽量定义为静态常量 在类的每个对象实例中,每个成员变量都有一份副本,而成员静态常量只有一份实例。 反例: public class HttpConnection { private final long timeout = 5L; ... } 正例: public class HttpConnection { private static final long TIMEOUT = 5L; ... } 1.3.尽量使用基本数据类型,避免自动装箱和拆箱 Java 中的基本数据类型double、float、long、int、short、char、boolean,分别对应包装类Double、Float、Long、Integer、Short、Character、Boolean。JVM支持基本类型与对应包装类的自动转换,被称为自动装箱和拆箱。装箱和拆箱都是需要CPU和内存资源的,所以应尽量避免使用自动装箱和拆箱。 反例: Integer sum = 0; int[] values = ...; for (int value : values) { sum += value; // 相当于result = Integer.valueOf(result.intValue() + value); } 正例: int sum = 0; int[] values = ...; for (int value : values) { sum += value; } 1.4.如果变量的初值会被覆盖,就没有必要给变量赋初值 反例: List<UserDO> userList = new ArrayList<>(); if (isAll) { userList = userDAO.queryAll(); } else { userList = userDAO.queryActive(); } 正例: List<UserDO> userList; if (isAll) { userList = userDAO.queryAll(); } else { userList = userDAO.queryActive(); } 1.5.尽量使用函数内的基本类型临时变量 在函数内,基本类型的参数和临时变量都保存在栈(Stack)中,访问速度较快;对象类型的参数和临时变量的引用都保存在栈(Stack)中,内容都保存在堆(Heap)中,访问速度较慢。在类中,任何类型的成员变量都保存在堆(Heap)中,访问速度较慢。 反例: public final class Accumulator { private double result = 0.0D; public void addAll(@NonNull double[] values) { for(double value : values) { result += value; } } ... } 正例: public final class Accumulator { private double result = 0.0D; public void addAll(@NonNull double[] values) { double sum = 0.0D; for(double value : values) { sum += value; } result += sum; } ... } 1.6.尽量不要在循环体外定义变量 在老版JDK中,建议“尽量不要在循环体内定义变量”,但是在新版的JDK中已经做了优化。通过对编译后的字节码分析,变量定义在循环体外和循环体内没有本质的区别,运行效率基本上是一样的。 反而,根据“ 局部变量作用域最小化 ”原则,变量定义在循环体内更科学更便于维护,避免了延长大对象生命周期导致延缓回收问题 。 反例: UserVO userVO; List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { userVO = new UserVO(); userVO.setId(userDO.getId()); ... userVOList.add(userVO); } 正例: List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); ... userVOList.add(userVO); } 1.7.不可变的静态常量,尽量使用非线程安全类 不可变的静态常量,虽然需要支持多线程访问,也可以使用非线程安全类。 反例: public static final Map<String, Class> CLASS_MAP; static { Map<String, Class> classMap = new ConcurrentHashMap<>(16); classMap.put("VARCHAR", java.lang.String.class); ... CLASS_MAP = Collections.unmodifiableMap(classMap); } 正例: public static final Map<String, Class> CLASS_MAP; static { Map<String, Class> classMap = new HashMap<>(16); classMap.put("VARCHAR", java.lang.String.class); ... CLASS_MAP = Collections.unmodifiableMap(classMap); } 1.8.不可变的成员变量,尽量使用非线程安全类 不可变的成员变量,虽然需要支持多线程访问,也可以使用非线程安全类。 反例: @Service public class StrategyFactory implements InitializingBean { @Autowired private List<Strategy> strategyList; private Map<String, Strategy> strategyMap; @Override public void afterPropertiesSet() { if (CollectionUtils.isNotEmpty(strategyList)) { int size = (int) Math.ceil(strategyList.size() * 4.0 / 3); Map<String, Strategy> map = new ConcurrentHashMap<>(size); for (Strategy strategy : strategyList) { map.put(strategy.getType(), strategy); } strategyMap = Collections.unmodifiableMap(map); } } ... } 正例: @Service public class StrategyFactory implements InitializingBean { @Autowired private List<Strategy> strategyList; private Map<String, Strategy> strategyMap; @Override public void afterPropertiesSet() { if (CollectionUtils.isNotEmpty(strategyList)) { int size = (int) Math.ceil(strategyList.size() * 4.0 / 3); Map<String, Strategy> map = new HashMap<>(size); for (Strategy strategy : strategyList) { map.put(strategy.getType(), strategy); } strategyMap = Collections.unmodifiableMap(map); } } ... 2.对象&类 2.1.禁止使用JSON转化对象 JSON提供把对象转化为JSON字符串、把JSON字符串转为对象的功能,于是被某些人用来转化对象。这种对象转化方式,虽然在功能上没有问题,但是在性能上却存在问题。 反例: List<UserDO> userDOList = ...; List<UserVO> userVOList = JSON.parseArray(JSON.toJSONString(userDOList), UserVO.class); 正例: List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); ... userVOList.add(userVO); } 2.2.尽量不使用反射赋值对象 用反射赋值对象,主要优点是节省了代码量,主要缺点却是性能有所下降。 反例: List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { UserVO userVO = new UserVO(); BeanUtils.copyProperties(userDO, userVO); userVOList.add(userVO); } 正例: List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); ... userVOList.add(userVO); } 2.3.采用Lambda表达式替换内部匿名类 对于大多数刚接触JDK8的同学来说,都会认为Lambda表达式就是匿名内部类的语法糖。实际上, Lambda表达式在大多数虚拟机中采用invokeDynamic指令实现,相对于匿名内部类在效率上会更高一些。 反例: List<User> userList = ...; Collections.sort(userList, new Comparator<User>() { @Override public int compare(User user1, User user2) { Long userId1 = user1.getId(); Long userId2 = user2.getId(); ... return userId1.compareTo(userId2); } }); 正例: List<User> userList = ...; Collections.sort(userList, (user1, user2) -> { Long userId1 = user1.getId(); Long userId2 = user2.getId(); ... return userId1.compareTo(userId2); }); 2.4.尽量避免定义不必要的子类 多一个类就需要多一份类加载,所以尽量避免定义不必要的子类。 反例: public static final Map<String, Class> CLASS_MAP = Collections.unmodifiableMap(new HashMap<String, Class>(16) { private static final long serialVersionUID = 1L; { put("VARCHAR", java.lang.String.class); } }); 正例: public static final Map<String, Class> CLASS_MAP; static { Map<String, Class> classMap = new HashMap<>(16); classMap.put("VARCHAR", java.lang.String.class); ... CLASS_MAP = Collections.unmodifiableMap(classMap); } 2.5.尽量指定类的final修饰符 为类指定final修饰符,可以让该类不可以被继承。如果指定了一个类为final,则该类所有的方法都是final的,Java编译器会寻找机会内联所有的final方法。内联对于提升Java运行效率作用重大,具体可参见Java运行期优化,能够使性能平均提高50%。 反例: public class DateHelper { ... } 正例: public final class DateHelper { ... } 注意:使用Spring的AOP特性时,需要对Bean进行动态代理,如果Bean类添加了final修饰,会导致异常。 3.方法 3.1.把跟类成员变量无关的方法声明成静态方法 静态方法的好处就是不用生成类的实例就可以直接调用。静态方法不再属于某个对象,而是属于它所在的类。只需要通过其类名就可以访问,不需要再消耗资源去反复创建对象。即便在类内部的私有方法,如果没有使用到类成员变量,也应该声明为静态方法。 反例: public int getMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.MONTH) + 1; } 正例: public static int getMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.MONTH) + 1; } 3.2.尽量使用基本数据类型作为方法参数类型,避免不必要的装箱、拆箱和空指针判断 反例: public static double sum(Double value1, Double value2) { double double1 = Objects.isNull(value1) ? 0.0D : value1; double double2 = Objects.isNull(value2) ? 0.0D : value2; return double1 + double2; } double result = sum(1.0D, 2.0D); 正例: public static double sum(double value1, double value2) { return value1 + value2; } double result = sum(1.0D, 2.0D); 3.3.尽量使用基本数据类型作为方法返回值类型,避免不必要的装箱、拆箱和空指针判断 在JDK类库的方法中,很多方法返回值都采用了基本数据类型,首先是为了避免不必要的装箱和拆箱,其次是为了避免返回值的空指针判断。比如:Collection.isEmpty()和Map.size()。 反例: public static Boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid()); } // 调用代码 UserDO user = ...; Boolean isValid = isValid(user); if (Objects.nonNull(isValid) && isValid.booleanValue()) { ... } 正例: public static boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid()); } // 调用代码 UserDO user = ...; if (isValid(user)) { ... } 3.4.协议方法参数值非空,避免不必要的空指针判断 协议编程,可以@NonNull和@Nullable标注参数,是否遵循全凭调用者自觉。 反例: public static boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid()); } 正例: public static boolean isValid(@NonNull UserDO user) { return Boolean.TRUE.equals(user.getIsValid()); } 3.5.协议方法返回值非空,避免不必要的空指针判断 协议编程,可以@NonNull和@Nullable标注参数,是否遵循全凭实现者自觉。 反例: // 定义接口 public interface OrderService { public List<OrderVO> queryUserOrder(Long userId); } // 调用代码 List<OrderVO> orderList = orderService.queryUserOrder(userId); if (CollectionUtils.isNotEmpty(orderList)) { for (OrderVO order : orderList) { ... } } 正例: // 定义接口 public interface OrderService { @NonNull public List<OrderVO> queryUserOrder(Long userId); } // 调用代码 List<OrderVO> orderList = orderService.queryUserOrder(userId); for (OrderVO order : orderList) { ... } 3.6.被调用方法已支持判空处理,调用方法无需再进行判空处理 反例: UserDO user = null; if (StringUtils.isNotBlank(value)) { user = JSON.parseObject(value, UserDO.class); } 正例: UserDO user = JSON.parseObject(value, UserDO.class); 3.7.尽量避免不必要的函数封装 方法调用会引起入栈和出栈,导致消耗更多的CPU和内存,应当尽量避免不必要的函数封装。当然,为了使代码更简洁、更清晰、更易维护,增加一定的方法调用所带来的性能损耗是值得的。 反例: // 函数封装 public static boolean isVip(Boolean isVip) { return Boolean.TRUE.equals(isVip); } // 使用代码 boolean isVip = isVip(user.getVip()); 正例: boolean isVip = Boolean.TRUE.equals(user.getVip()); 3.8.尽量指定方法的final修饰符 方法指定final修饰符,可以让方法不可以被重写,Java编译器会寻找机会内联所有的final方法。内联对于提升Java运行效率作用重大,具体可参见Java运行期优化,能够使性能平均提高50%。 注意:所有的private方法会隐式地被指定final修饰符,所以无须再为其指定final修饰符。 反例: public class Rectangle { ... public double area() { ... } } 正例: public class Rectangle { ... public final double area() { ... } } 注意:使用Spring的AOP特性时,需要对Bean进行动态代理,如果方法添加了final修饰,将不会被代理。 4.表达式 4.1.尽量减少方法的重复调用 反例: List<UserDO> userList = ...; for (int i = 0; i < userList.size(); i++) { ... } 正例: List<UserDO> userList = ...; int userLength = userList.size(); for (int i = 0; i < userLength; i++) { ... } 4.2.尽量避免不必要的方法调用 反例: List<UserDO> userList = userDAO.queryActive(); if (isAll) { userList = userDAO.queryAll(); } 正例: List<UserDO> userList; if (isAll) { userList = userDAO.queryAll(); } else { userList = userDAO.queryActive(); } 4.3.尽量使用移位来代替正整数乘除 用移位操作可以极大地提高性能。对于乘除2^n(n为正整数)的正整数计算,可以用移位操作来代替。 反例: int num1 = a * 4; int num2 = a / 4; 正例: int num1 = a << 2; int num2 = a >> 2; 4.4.提取公共表达式,避免重复计算 提取公共表达式,只计算一次值,然后重复利用值。 反例: double distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); 正例: double dx = x2 - x1; double dy = y2 - y1; double distance = Math.sqrt(dx * dx + dy * dy); 或 double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); 4.5.尽量不在条件表达式中用!取反 使用!取反会多一次计算,如果没有必要则优化掉。 反例: if (!(a >= 10)) { ... // 条件处理1 } else { ... // 条件处理2 } 正例: if (a < 10) { ... // 条件处理1 } else { ... // 条件处理2 } 4.6.对于多常量选择分支,尽量使用switch语句而不是if-else语句 if-else语句,每个if条件语句都要加装计算,直到if条件语句为true为止。switch语句进行了跳转优化,Java中采用tableswitch或lookupswitch指令实现,对于多常量选择分支处理效率更高。经过试验证明:在每个分支出现概率相同的情况下,低于5个分支时if-else语句效率更高,高于5个分支时switch语句效率更高。 反例: if (i == 1) { ...; // 分支1 } else if (i == 2) { ...; // 分支2 } else if (i == ...) { ...; // 分支n } else { ...; // 分支n+1 } 正例: switch (i) { case 1 : ... // 分支1 break; case 2 : ... // 分支2 break; case ... : ... // 分支n break; default : ... // 分支n+1 break; } 备注:如果业务复杂,可以采用Map实现策略模式。 5.字符串 5.1.尽量不要使用正则表达式匹配 正则表达式匹配效率较低,尽量使用字符串匹配操作。 反例: String source = "a::1,b::2,c::3,d::4"; String target = source.replaceAll("::", "="); Stringp[] targets = source.spit("::"); 正例: String source = "a::1,b::2,c::3,d::4"; String target = source.replace("::", "="); Stringp[] targets = StringUtils.split(source, "::"); 5.2.尽量使用字符替换字符串 字符串的长度不确定,而字符的长度固定为1,查找和匹配的效率自然提高了。 反例: String source = "a:1,b:2,c:3,d:4"; int index = source.indexOf(":"); String target = source.replace(":", "="); 正例: String source = "a:1,b:2,c:3,d:4"; int index = source.indexOf(':'); String target = source.replace(':', '='); 5.3.尽量使用StringBuilder进行字符串拼接 String是final类,内容不可修改,所以每次字符串拼接都会生成一个新对象。StringBuilder在初始化时申请了一块内存,以后的字符串拼接都在这块内存中执行,不会申请新内存和生成新对象。 反例: String s = ""; for (int i = 0; i < 10; i++) { if (i != 0) { s += ','; } s += i; } 正例: StringBuilder sb = new StringBuilder(128); for (int i = 0; i < 10; i++) { if (i != 0) { sb.append(','); } sb.append(i); } 5.4.不要使用""+转化字符串 使用""+进行字符串转化,使用方便但是效率低,建议使用String.valueOf. 反例: int i = 12345; String s = "" + i; 正例: int i = 12345; String s = String.valueOf(i); 6.数组 6.1.不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组 推荐使用System.arraycopy拷贝数组,也可以使用Arrays.copyOf拷贝数组。 反例: int[] sources = new int[] {1, 2, 3, 4, 5}; int[] targets = new int[sources.length]; for (int i = 0; i < targets.length; i++) { targets[i] = sources[i]; } 正例: int[] sources = new int[] {1, 2, 3, 4, 5}; int[] targets = new int[sources.length]; System.arraycopy(sources, 0, targets, 0, targets.length); 6.2.集合转化为类型T数组时,尽量传入空数组T[0] 将集合转换为数组有2种形式:toArray(new T[n])和toArray(new T[0])。在旧的Java版本中,建议使用toArray(new T[n]),因为创建数组时所需的反射调用非常慢。在OpenJDK6后,反射调用是内在的,使得性能得以提高,toArray(new T[0])比toArray(new T[n])效率更高。此外,toArray(new T[n])比toArray(new T[0])多获取一次列表大小,如果计算列表大小耗时过长,也会导致toArray(new T[n])效率降低。 反例: List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...); Integer[] integers = integerList.toArray(new Integer[integerList.size()]); 正例: List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...); Integer[] integers = integerList.toArray(new Integer[0]); // 勿用new Integer[]{} 建议:集合应该提供一个toArray(Class clazz)方法,避免无用的空数组初始化(new T[0])。 6.3.集合转化为Object数组时,尽量使用toArray()方法 转化Object数组时,没有必要使用toArray[new Object[0]],可以直接使用toArray()。避免了类型的判断,也避免了空数组的申请,所以效率会更高。 反例: List<Object> objectList = Arrays.asList(1, "2", 3, "4", 5, ...); Object[] objects = objectList.toArray(new Object[0]); 正例: List<Object> objectList = Arrays.asList(1, "2", 3, "4", 5, ...); Object[] objects = objectList.toArray(); 7.集合 7.1.初始化集合时,尽量指定集合大小 Java集合初始化时都会指定一个默认大小,当默认大小不再满足数据需求时就会扩容,每次扩容的时间复杂度有可能是O(n)。所以,尽量指定预知的集合大小,就能避免或减少集合的扩容次数。 反例: List<UserDO> userDOList = ...; Set<Long> userSet = new HashSet<>(); Map<Long, UserDO> userMap = new HashMap<>(); List<UserVO> userList = new ArrayList<>(); for (UserDO userDO : userDOList) { userSet.add(userDO.getId()); userMap.put(userDO.getId(), userDO); userList.add(transUser(userDO)); } 正例: List<UserDO> userDOList = ...; int userSize = userDOList.size(); Set<Long> userSet = new HashSet<>(userSize); Map<Long, UserDO> userMap = new HashMap<>((int) Math.ceil(userSize * 4.0 / 3)); List<UserVO> userList = new ArrayList<>(userSize); for (UserDO userDO : userDOList) { userSet.add(userDO.getId()); userMap.put(userDO.getId(), userDO); userList.add(transUser(userDO)); } 7.2.不要使用循环拷贝集合,尽量使用JDK提供的方法拷贝集合 JDK提供的方法可以一步指定集合的容量,避免多次扩容浪费时间和空间。同时,这些方法的底层也是调用System.arraycopy方法实现,进行数据的批量拷贝效率更高。 反例: List<UserDO> user1List = ...; List<UserDO> user2List = ...; List<UserDO> userList = new ArrayList<>(user1List.size() + user2List.size()); for (UserDO user1 : user1List) { userList.add(user1); } for (UserDO user2 : user2List) { userList.add(user2); } 正例: List<UserDO> user1List = ...; List<UserDO> user2List = ...; List<UserDO> userList = new ArrayList<>(user1List.size() + user2List.size()); userList.addAll(user1List); userList.addAll(user2List); 7.3.尽量使用Arrays.asList转化数组为列表 原理与"不要使用循环拷贝集合,尽量使用JDK提供的方法拷贝集合"类似。 反例: List<String> typeList = new ArrayList<>(8); typeList.add("Short"); typeList.add("Integer"); typeList.add("Long"); String[] names = ...; List<String> nameList = ...; for (String name : names) { nameList.add(name); } 正例: List<String> typeList = Arrays.asList("Short", "Integer", "Long"); String[] names = ...; List<String> nameList = ...; nameList.addAll(Arrays.asList(names)); 7.4.直接迭代需要使用的集合 直接迭代需要使用的集合,无需通过其它操作获取数据。 反例: Map<Long, UserDO> userMap = ...; for (Long userId : userMap.keySet()) { UserDO user = userMap.get(userId); ... } 正例: Map<Long, UserDO> userMap = ...; for (Map.Entry<Long, UserDO> userEntry : userMap.entrySet()) { Long userId = userEntry.getKey(); UserDO user = userEntry.getValue(); ... } 7.5.不要使用size方法检测空,必须使用isEmpty方法检测空 使用size方法来检测空逻辑上没有问题,但使用isEmpty方法使得代码更易读,并且可以获得更好的性能。任何isEmpty方法实现的时间复杂度都是O(1),但是某些size方法实现的时间复杂度有可能是O(n)。 反例: List<UserDO> userList = ...; if (userList.size() == 0) { ... } Map<Long, UserDO> userMap = ...; if (userMap.size() == 0) { ... } 正例: List<UserDO> userList = ...; if (userList.isEmpty()) { ... } Map<Long, UserDO> userMap = ...; if (userMap.isEmpty()) { ... } 7.6.非随机访问的List,尽量使用迭代代替随机访问 对于列表,可分为随机访问和非随机访问两类,可以用是否实现RandomAccess接口判断。随机访问列表,直接通过get获取数据不影响效率。而非随机访问列表,通过get获取数据效率极低。 反例: LinkedList<UserDO> userDOList = ...; int size = userDOList.size(); for (int i = 0; i < size; i++) { UserDO userDO = userDOList.get(i); ... } 正例: LinkedList<UserDO> userDOList = ...; for (UserDO userDO : userDOList) { ... } 其实,不管列表支不支持随机访问,都应该使用迭代进行遍历。 7.7.尽量使用HashSet判断值存在 在Java集合类库中,List的contains方法普遍时间复杂度是O(n),而HashSet的时间复杂度为O(1)。如果需要频繁调用contains方法查找数据,可以先将List转换成HashSet。 反例: List<Long> adminIdList = ...; List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { if (adminIdList.contains(userDO.getId())) { userVOList.add(transUser(userDO)); } } 正例: Set<Long> adminIdSet = ...; List<UserDO> userDOList = ...; List<UserVO> userVOList = new ArrayList<>(userDOList.size()); for (UserDO userDO : userDOList) { if (adminIdSet.contains(userDO.getId())) { userVOList.add(transUser(userDO)); } } 7.8.避免先判断存在再进行获取 如果需要先判断存在再进行获取,可以直接获取并判断空,从而避免了二次查找操作。 反例: public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) { UserVO userVO = new UserVO(); userVO.setId(user.getId()); ... if (roleMap.contains(user.getRoleId())) { RoleDO role = roleMap.get(user.getRoleId()); userVO.setRole(transRole(role)); } } 正例: public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) { UserVO userVO = new UserVO(); userVO.setId(user.getId()); ... RoleDO role = roleMap.get(user.getRoleId()); if (Objects.nonNull(role)) { userVO.setRole(transRole(role)); } } 8.异常 8.1.直接捕获对应的异常 直接捕获对应的异常,避免用instanceof判断,效率更高代码更简洁。 反例: try { saveData(); } catch (Exception e) { if (e instanceof IOException) { log.error("保存数据IO异常", e); } else { log.error("保存数据其它异常", e); } } 正例: try { saveData(); } catch (IOException e) { log.error("保存数据IO异常", e); } catch (Exception e) { log.error("保存数据其它异常", e); } 8.2.尽量避免在循环中捕获异常 当循环体抛出异常后,无需循环继续执行时,没有必要在循环体中捕获异常。因为,过多的捕获异常会降低程序执行效率。 反例: public Double sum(List<String> valueList) { double sum = 0.0D; for (String value : valueList) { try { sum += Double.parseDouble(value); } catch (NumberFormatException e) { return null; } } return sum; } 正例: public Double sum(List<String> valueList) { double sum = 0.0D; try { for (String value : valueList) { sum += Double.parseDouble(value); } } catch (NumberFormatException e) { return null; } return sum; } 8.3.禁止使用异常控制业务流程 相对于条件表达式,异常的处理效率更低。 反例: public static boolean isValid(UserDO user) { try { return Boolean.TRUE.equals(user.getIsValid()); } catch(NullPointerException e) { return false; } } 正例: public static boolean isValid(UserDO user) { if (Objects.isNull(user)) { return false; } return Boolean.TRUE.equals(user.getIsValid()); } 9.缓冲区 9.1.初始化时尽量指定缓冲区大小 初始化时,指定缓冲区的预期容量大小,避免多次扩容浪费时间和空间。 反例: StringBuffer buffer = new StringBuffer(); StringBuilder builder = new StringBuilder(); 正例: StringBuffer buffer = new StringBuffer(1024); StringBuilder builder = new StringBuilder(1024); 9.2.尽量重复使用同一缓冲区 针对缓冲区,Java虚拟机需要花时间生成对象,还要花时间进行垃圾回收处理。所以,尽量重复利用缓冲区。 反例: StringBuilder builder1 = new StringBuilder(128); builder1.append("update t_user set name = '").append(userName).append("' where id = ").append(userId); statement.executeUpdate(builder1.toString()); StringBuilder builder2 = new StringBuilder(128); builder2.append("select id, name from t_user where id = ").append(userId); ResultSet resultSet = statement.executeQuery(builder2.toString()); ... 正例: StringBuilder builder = new StringBuilder(128); builder.append("update t_user set name = '").append(userName).append("' where id = ").append(userId); statement.executeUpdate(builder.toString()); builder.setLength(0); builder.append("select id, name from t_user where id = ").append(userId); ResultSet resultSet = statement.executeQuery(builder.toString()); ... 其中,使用setLength方法让缓冲区重新从0开始。 9.3.尽量设计使用同一缓冲区 为了提高程序运行效率,在设计上尽量使用同一缓冲区。 反例: // 转化XML(UserDO) public static String toXml(UserDO user) { StringBuilder builder = new StringBuilder(128); builder.append("<UserDO>"); builder.append(toXml(user.getId())); builder.append(toXml(user.getName())); builder.append(toXml(user.getRole())); builder.append("</UserDO>"); return builder.toString(); } // 转化XML(Long) public static String toXml(Long value) { StringBuilder builder = new StringBuilder(128); builder.append("<Long>"); builder.append(value); builder.append("</Long>"); return builder.toString(); } ... // 使用代码 UserDO user = ...; String xml = toXml(user); 正例: // 转化XML(UserDO) public static void toXml(StringBuilder builder, UserDO user) { builder.append("<UserDO>"); toXml(builder, user.getId()); toXml(builder, user.getName()); toXml(builder, user.getRole()); builder.append("</UserDO>"); } // 转化XML(Long) public static void toXml(StringBuilder builder, Long value) { builder.append("<Long>"); builder.append(value); builder.append("</Long>"); } ... // 使用代码 UserDO user = ...; StringBuilder builder = new StringBuilder(1024); toXml(builder, user); String xml = builder.toString(); 去掉每个转化方法中的缓冲区申请,申请一个缓冲区给每个转化方法使用。从时间上来说,节约了大量缓冲区的申请释放时间;从空间上来说,节约了大量缓冲区的临时存储空间。 9.4.尽量使用缓冲流减少IO操作 使用缓冲流BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream等,可以大幅较少IO次数并提升IO速度。 反例: try (FileInputStream input = new FileInputStream("a"); FileOutputStream output = new FileOutputStream("b")) { int size = 0; byte[] temp = new byte[1024]; while ((size = input.read(temp)) != -1) { output.write(temp, 0, size); } } catch (IOException e) { log.error("复制文件异常", e); } 正例: try (BufferedInputStream input = new BufferedInputStream(new FileInputStream("a")); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("b"))) { int size = 0; byte[] temp = new byte[1024]; while ((size = input.read(temp)) != -1) { output.write(temp, 0, size); } } catch (IOException e) { log.error("复制文件异常", e); } 其中,可以根据实际情况手动指定缓冲流的大小,把缓冲流的缓冲作用发挥到最大。 10.线程 10.1.在单线程中,尽量使用非线程安全类 使用非线程安全类,避免了不必要的同步开销。 反例: StringBuffer buffer = new StringBuffer(128); buffer.append("select * from ").append(T_USER).append(" where id = ?"); 正例: StringBuilder buffer = new StringBuilder(128); buffer.append("select * from ").append(T_USER).append(" where id = ?"); 10.2.在多线程中,尽量使用线程安全类 使用线程安全类,比自己实现的同步代码更简洁更高效。 反例: private volatile int counter = 0; public void access(Long userId) { synchronized (this) { counter++; } ... } 正例: private final AtomicInteger counter = new AtomicInteger(0); public void access(Long userId) { counter.incrementAndGet(); ... } 10.3.尽量减少同步代码块范围 在一个方法中,可能只有一小部分的逻辑是需要同步控制的,如果同步控制了整个方法会影响执行效率。所以,尽量减少同步代码块的范围,只对需要进行同步的代码进行同步。 反例: private volatile int counter = 0; public synchronized void access(Long userId) { counter++; ... // 非同步操作 } 正例: private volatile int counter = 0; public void access(Long userId) { synchronized (this) { counter++; } ... // 非同步操作 } 10.4.尽量合并为同一同步代码块 同步代码块是有性能开销的,如果确定可以合并为同一同步代码块,就应该尽量合并为同一同步代码块。 反例: // 处理单一订单 public synchronized handleOrder(OrderDO order) { ... } // 处理所有订单 public void handleOrder(List<OrderDO> orderList) { for (OrderDO order : orderList) { handleOrder(order); } } 正例: // 处理单一订单 public handleOrder(OrderDO order) { ... } // 处理所有订单 public synchronized void handleOrder(List<OrderDO> orderList) { for (OrderDO order : orderList) { handleOrder(order); } } 10.5.尽量使用线程池减少线程开销 多线程中两个必要的开销:线程的创建和上下文切换。采用线程池,可以尽量地避免这些开销。 反例: public void executeTask(Runnable runnable) { new Thread(runnable).start(); } 正例: private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(10); public void executeTask(Runnable runnable) { executorService.execute(runnable); } 后记 作为一名长期奋战在业务一线的"IT民工",没有机会去研究什么高深莫测的"理论",只能专注于眼前看得见摸得着的"技术",致力于做到"干一行、爱一行、专一行、精一行"。 原文发布时间:2019-12-18作者:常意本文来自阿里云合作伙伴“阿里技术”,了解相关信息可以关注“阿里技术”。

优秀的个人博客,低调大师

Python全栈工程师(文件操作、编码)

ParisGabriel 每天坚持手写一天一篇 决定坚持几年 为了梦想为了信仰 Python人工智能从入门到精通 最近简直要死了 发烧感冒 喉咙痛。。。。、 如何长期保存计算机中数据: 需要文件操作 文件 file: 文件是用于数据存储的单位 文件通常用来长期储存数据 文件中的数据是以字节为单位进行顺序储存的文件的操作流程: 1.打开文件 2.读/写文件 3.关闭文件 注: 任何操作系统, 一个应用程序同时打开文件的数量有最大数限制文件打开函数: open(file, mode=‘rt’) 用于打开一个文件, 返回此文件流对象, 如果打开文件失败, 则会触发osError错误文件的关闭方法: F.colse() #关闭问津, 释放系统资源 示例: # 此示例示意文件的打开和关闭操作 try: f = open('./aaa.txt') # 不存在此文件 # f = open('./myfile.txt') # 不存在此文件 print("打开文件成功") # 此处要进行读/写操作 f.close() # 半闭文件 except OSError: print("文件打开失败") 文件方法: 文件 mode 模式字符的含义 字符 含义 'r' 以只读方式打开(默认) 'w' 以只写方式打开,删除原有文件内容(如果文件不存在,则创建该文件并以只写方式打开) 'x' 创建一个新文件, 并以写模式打开这个文件,如果文件存在则会产生"FileExistsError"错误 'a' 以只写文件打开一个文件,如果有原文件则追加到文件末尾 'b' 用二进制模式打开 't' 文本文件模式打开 (默认) '+' 为更新内容打开一个磁盘文件 (可读可写) 缺省模式是 'rt' 'w+b' 可以实现二进制随机读写,当打开文件时,文件内容将被清零 'r+b' 以二进制读和更新模式打开文件,打开文件时不会清空文件内容 'r+' 以文本模式读和更新模式打开文件,打开文件时不会清空文件内容 python 文件常用方法: 方法 说明 F.close() 关闭文件(关闭后文件不能再读写会发生ValueError错误) F.readline() 读取一行数据, 如果到达文件尾则返回空行 F.readlines(max_chars=-1) 返回每行字符串的列表,max_chars为最大字符(或字节)数 F.writelines(lines) 将字符串的列表或字符串的列表中的内容写入文件 二进制文件操作方法 F.read(size=-1) 从一个文件流中最多读取size个字符(文本文件)或字节(二进制文件),如果不给出参数,则默认读取文件中全部的内容并返回 F.write(text) 写一个字符串到文件流中,返回写入的字符数(文本文件)或字节数(二进制文件) F.tell() 返回当前文件流读写指针的绝对位置(字节为单位) F.seek(offset, whence=0) 改变数据流读写指针的位置,返回新的绝对位置 F.flush() 把写入文件对象的缓存内容写入到磁盘 F.readable() 判断这个文件是否可读,可读返回True,否则返回False F.writable() 判断这个文件是否可写,可写返回True,否则返回False F.seekable() 返回这个文件对象是否支持随机定位 F.truncate(pos = None) 剪掉 自pos位置之后的数据,返回新的文件长度 文本文件操作: 操作模式: ‘t’ 说明: 1.默认文件中储存的都为字节数据, 在读写过程中会自动进行编解码操作 2.文本文件以行位单位进行分割, 在python内部统一用"\n"做为换行符进行分割 3.对文本文件的读写操作需要用字符串(str)进行数据操作 Linux换行符: '\n' Windows 换行符: '\r\n' 新的Mac OS 换行符: '\n' 旧的Macintosh换行符: '\r'(已不用了) 文件流对象是可迭代对象, 迭代过程中将换行符“\n”作为分隔符 f = open('phonenumber.txt') for line in f: print(line) # 打印每一行的数据 标准输入输出文件: sys.stdin 标准输入文件 Ctrl + D 输入文件结束符 sys.stdout 标准输出文件 sys.stderr 标准错误输出文件 标准文件绝对不能关闭 Linux系统内所有的硬件都会映射成文件 关闭文件会导致错误模块:sys 注: 标准文件不需要打开和关闭就可以使用 示例: import sys sys.stdout.write("我是标准输出\n") sys.stderr.write("我是一个错误\n") import sys s = sys.stdin.read() print("s=", s) print("程序结束") 二进制文件操作: 二进制文件操作模式字符:‘b’ 默认文件中存储的是以字节数据为单位, 通常有人为规定的格式 二进制文件操作需要用字节串进行读写 F.read()/F.readline() F.readlines()返回类型 对于文本操作 F.write() 对于二进制文件也需要用字节串进行操作 F.tell: 作用: 返回当前的读写位置(从文件头以字节为单位) F.seek方法: F.seek(偏移量,whence=相对位置) 偏移量 大于0的数代表向文件尾方向移动的字节数 小于0的数代表向文件头方向移动的字节数 相对位置 0代表从文件头开始偏移 1代表从文件当前位置开始偏移 2代表从文件尾开始偏移 (第一个参数必须是负的) 示例: # 此示例示意用seek改变文件的读写位置,用tell来得到读写位置 f = open('myseek.txt', 'rb') b = f.read(2) # b'AB' 读取出来 print(b) # b'AB # 从头开始向后走5个字节 # f.seek(5, 0) # 从当前位置向后走3个字节 # f.seek(3, 1) # 从文件尾向前数15个字节 f.seek(-15, 2) b = f.read(5) print(b) # b'abcde' f.close() 汉字编码(只讲两种) 国标系列: GB18030(二字节或四字节编码27553个字) GBk(二字节编码21003个字) GB2312(二字节编码6763个字) (Windows 常用) 国际标准: Unicode <---> UTF-8 (Ascii 占1字节 汉字占3字节) (Linux Mac OS X / IOS /Android) python编码字符串: ‘gb18030’ ‘gb2312’ ‘gbk’ ‘utf-8’ ‘ascii’ ....以上字符串用于encide和decode中编码注释: 在Python源文件中的第一行或第二行写入如下内容: # -*- codeing:gbk -*- #设置源文件编码格式为gbk 或 # -*- codeing:utf-8 -*- #设置源文件编码格式为utf-8 作用: 告诉解释执行器此文件的编码是什么 练习: 自己写一个文件 'info.txt' 内部存一些文字信息 如: 张三 20 100 李四 21 96 小王 22 98 写程序将这些数据读取出来,打印到终端上 答案: try: f = open("myfile.txt") L = f.readlines() for x in L: s = x.strip() n, a, s = s.split() print("姓名:", n, "年龄:", int(a), "成绩:", int(s)) except: print("打开文件是失败") 练习: 1. 写程序,循环输入很多个人的姓名,电话号码, 当输入结束后将这些信息存入到文件phonenumber.txt中 (建议先用列表暂存数据,格式自己定义) 2. 写程序,将phonenumber.txt文件中的数据读取出来. 再用以下格式打印出来: 如: 小张 的电话是 13888888888 小李 的电话是 13999999999 练习: 1. 写程序实现复制文件的功能 要求: 1. 要考虑特大文件问题 2. 要关闭文件 3. 要能复制二进制文件 如: 请输入源文件路径名: /home/tarena/xxx.tar.gz 请输入目标文件路径名: ./a.tar.gz 显示: 文件已成功复制 答案: def copy_myfile(): try: ypath = input("please inout raw path:") xpath = input("please inout new path:") f1 = open(xpath, "w+b") f = open(ypath, "r+b") for x in f: f1.write(x) f1.close() f.close() print("File copied") except: print("file not inexeistence") copy_myfile() 2. 修改学生信息管理程序,要求加入两个功能: 9) 保存信息到文件(si.txt) L = [{"name": "Tom", "age": 20, "score": 98}, {"name": "Lin", "age": 21, "score": 99}, {"name": "Garin", "age": 19, "score": 100}] def student_file(L): try: f = open("./si.txt", "x") for x in L: f.write(x["name"]) f.write(" ") f.write(str(x["age"])) f.write(" ") f.write(str(x["score"])) f.write("\n") except FileExistsError: f = open("./si.txt", "a") for x in L: f.write(x["name"]) f.write(" ") f.write(str(x["age"])) f.write(" ") f.write(str(x["score"])) f.write("\n") student_file(L) 10) 从文件中读取数据(si.tx def open_student_file(): f = open("./si.txt") L = [] for line in f.readlines(): s = line.strip() n, a, s = s.split() # 拆成列表 student = {"name": n, "age": a, "score": s} L.append(student) f.close() return L 源码: https://pan.baidu.com/s/1vVuH7OwNdn8vqaBKAivniQ异常还没处理...........

优秀的个人博客,低调大师

Python全栈工程师(每周总结:3)

ParisGabriel 每天坚持 一天一篇 点个订阅吧灰常感谢 当个死粉也阔以 week summer: Python人工智能从入门到精通 函数式编程: 是指用一系列函数解决问题 每一个函数完成细小的功能,一系列函数的任意组合可以完成大问题 函数仅接受输入并产生输入,不包含任何影响输出的内部 状态函数的可重用性: 如果一个函数的输入参数一定,则返回结果必须一定的函数 称为可重用函数 可重入和不可重入区别就是访问除局部变量以外的变量函数式编程要求: def 创建函数最好不要访问局部作用域以外的变量,这样可以保证 结果的唯一性(可重入性)高阶函数 high order function: 满足下列条件之一的就是高阶函数 1.函数接受一个或多个函数作用参数传入 2.函数返回一个函数 内建高阶函数: map,filter,sorted map(func, *iterables): 用函数和对可迭代对象中的每一个元素作为参数计算出新的可迭代对象, 当最短的一个可迭代对象不再提供数据时此可迭代对象生成结束 func 函数 *iterables 排列 filter(function, iterable): 筛选可迭代对象iterable中的数据,返回一个可迭代器对象,此可迭代对象 将对iterable进行筛选.函数function 将对iterable中的每个元素进行求值, 返回False则将此数据丢弃,返回True,则保留此数据 sorted(iterable, key=None, reverse=False): 将原可迭代对象的数据进行排序,生成排序后的列表iterable 可迭代对象 key 函数是用来提供一个值,这个值将作为排序的依据reverse 标志用来设 置是否降序排序 返回可迭代对象函数: range() map() filter() reverse()递归函数; 函数直接调用或间接的调用自身 直接调用自己 def f(): f() 间接调用自己 def fa(): fb() def fb(): fa() 递归一定要控制递归的层数,当符合条件时要终止递归 几乎所有的递归都能用while循环来代替递归特点: 优点: 递归吧问题简单化,让思路更清晰,代码更简洁 缺点: 递归因系统环境影响大,当递归深时,可能会得到不可预知的结果 递推阶段: 从原问题出发,按递归公式递推从未知到已知,最终达到递归的终止条件 回归阶段 按递归终止条件求出结果,逆向逐步代入递归公式 回归到原问题求解 闭包 closure: 闭包是引用了此函数外部的变量函数 闭包是将内部嵌套和函数外部的执行环境绑定在一起的对象 装饰器 decorators(专业提高篇) 装饰器是一个函数 ,主要用来包装另一个函数或类 装饰的目的是在 不改变函数的的原名(或类名)的情况下 改变对象的行为函数装饰器 函数装饰器指装饰器传入的是一个函数,返回的也是一个函数 原理就是改变原变量绑定的函数函数的文档字符串: 函数内第一次未被赋值给任何变量的字符串是此函数的文档字符串 模块 Module: 模块是一个包含有一系列数据、函数、类等组成的程序组 模块是一个文件,模块文件通常以.py结尾 作用: 让一些相关的数据、函数、类等有逻辑的组织在一起,使用逻辑结构清晰 模块的数据、函数、类等 可提供给其他模块或程序使用模块的分类; 内建模块(builtins)在解析器的内可以直接使用、 标准库模块,安装python时已安装且可以使用 第三方模块(通常开源),需要自己安装 用户自己编写模块(可以作为其他人的第三方模块) import 将某模块整体导入到当前模块中 from import 将谋模块的一个或多个属性导入到当前模块的作用域 from import * 将某模块的所有属性全部导入到当前模块dir函数: dir([对象]) 返回一个字符串的列表 不给参数这返回当前作用域内的所有变量的列表 内建模块 数学模块用法: import math # 或 from math import * 变量 描述 math.e 自然对数的底e math.pi 圆周率pi 函数名 描述math.ceil(x) 对x向上取整,比如x=1.2,返回2math.floor(x) 对x向下取整,比如x=1.2,返回1math.sqrt(x) 返回x的平方根math.factorial(x) 求x的阶乘math.log(x[, base]) 返回以base为底x的对数, 如果不给出base,则以自然对数e为底math.log10(x) 求以10为底x的对数math.pow(x, y) 返回 x**y (x的y次方)math.fabs(x) 返回浮点数x的绝对值角度和弧度degrees互换 math.degree(x) 将弧度x转换为角度math.radians(x) 将角度x转换为弧度三角函数 math.sin(x) 返回x的正弦(x为弧度)math.cos(x) 返回x的余弦(x为弧度)math.tan(x) 返回x的正切(x为弧度)math.asin(x) 返回x的反正弦(返回值为为弧度)math.acos(x) 返回x的反余弦(返回值为为弧度)math.atan(x) 返回x的反正切(返回值为为弧度) 时间模块 time 此模块提供了时间相关的函数,且一直可用 时间简介 公元纪年是从公元 0000年1月1日0时开始的 计算机元年是从1970年1月1日0时开始的,此时时间为0,之后每过一秒时间+1 UTC 时间 (Coordinated Universal Time) 是从Greenwich时间开始计算的. UTC 时间不会因时区问题而产生错误 DST 阳光节约时间(Daylight Saving Time),又称夏令时, 是一个经过日照时间修正后的时间 时间元组 时间元组是一个9个整型元素组成的,这九个元素自前至后依次为: 四位的年(如: 1993) 月 (1-12) 日 (1-31) 时 (0-23) 分 (0-59) 秒 (0-59) 星期几 (0-6, 周一是 0) 元旦开始日 (1-366) 夏令时修正时间 (-1, 0 or 1). 注: 如果年份值小于100,则会自动转换为加上1900后的值 模块名: time 时间模块用法: import time # 或 from time import xxx # 或 from time import * 变量 描述 time.altzone 夏令时时间与UTC时间差(秒为单位) time.daylight 夏令时校正时间 time.timezone 本地区时间与UTC时间差(秒为单位) time.tzname 时区名字的元组, 第一个名字为未经夏令时修正的时区名, 第一个名字为经夏令时修正后的时区名 注: CST为中国标准时间(China Standard Time UTC+8:00) 函数名 描述 time.time() 返回从计算机元年至当前时间的秒数的浮点数(UTC时间为准) time.sleep(secs) 让程序按给定秒数的浮点数睡眠一段时间 time.gmtime([secs]) 用给定秒数转换为用UTC表达的时间元组 (缺省返回当前时间元组) time.asctime([tuple]) 将时间元组转换为日期时间字符串 time.mktime(tuple) 将本地日期时间元组转换为新纪元秒数时间(UTC为准) time.localtime([secs]) 将UTC秒数时间转换为日期元组(以本地时间为准) 系统模块 sys 运行时系统相关的信息 sys模块的属性 属性 描述sys.path 模块搜索路径 path[0] 是当前脚本程序的路径名,否则为 ''sys.modules 已加载模块的字典sys.version 版本信息字符串sys.version_info 版本信息的命名元组sys.platform 操作系统平台名称信息sys.argv 命令行参数 argv[0] 代表当前脚本程序路径名sys.copyright 获得Python版权相关的信息sys.builtin_module_names 获得Python内建模块的名称(字符串元组)sys模块的函数 函数名 描述sys.exit([arg]) 退出程序,正常退出时sys.exit(0)sys.getrecursionlimit() 得到递归嵌套层次限制(栈的深度)sys.setrecursionlimit(n) 得到和修改递归嵌套层次限制(栈的深度) $ pip3 install tensorflow 第三方模块 tensorflow 的安装 必须有网 命令自动下载安装 自定义模块文件名必须是标识符模块的加载过程: 1. 在模块导入时,模块的所有语句都会执行 2. 如果一个模块已经导入,则再次导入时不会重新执行模块内的语句 重新加载mymodl1模块 import imp imp.reload(mymodl1) __doc__属性 文档字符串自动赋值给__file__ 属性 查看模块的当前路径dir(模块名) 查看模块属性模块以导入和执行的过程: 1. 先搜索相关的路径,找到模块名.py 2. 判断是否有此模块对应的.pyc文件。如果.pyc比.py文件新,则直接加载.pyc文件 3. 否则 用模块.py,文件生成.pyc,并加载执行 pyc python的编译 编译 解释执行 mymod.py --------> mymod.pyc --------> python3 模块的文档字符串和函数一样 模块的 __doc__ 属性 此属性用于绑定模块的文档字符串 模块的 __file__属性 此属性用于记录模块对应的文件路径名 模块的 __name__属性 __name__属性 用来记录模块自身名字 判断是否为主模块 主模块: __name__绑定 '__main__' 非主模块: __name__ 绑定模块名 模块的 __all__列表 模块中的 __all__列表是一个用来存放可导出属性的字符串列表 模块的隐藏属性 模块中以'_'开头的属性,在from xxx import * 导入时,通常将不被导入 标准库模块 随机模块 random说明: random模块是用于模拟或生成随机输出的模块. import random as R 函数名 描述R.random() 返回一个[0, 1) 之间的随机实数R.uniform(a,b) 返回[a,b) 区间内的随机实数R.randrange([start,] stop[, step]) 返回range(start,stop,step)中的随机数R.choice(seq) 从序列中返回随意元素R.shuffle(seq[, random]) 随机指定序列的顺序(乱序序列)R.sample(seq,n) 从序列中选择n个随机且不重复的元素包(模块包) package 包是将模块以文件夹的组织形式进行分组管理的管理方法 __init__.py是常规包内必须存在的文件 __init__.py会在包加载时自动调用 __init__.py : 1. 编写此包的内容 2. 在内部填写文档字符串 . 在__init__.py文件内可以加载此包所依懒的一些其它模块 __init__.py内的 __all__ 列表 用来记录此包中有哪些子包或模块在用from import *语句 时被导入 __all__列表只对 from xxx import *语句起作用 导入包时的索引路径顺序: 1. 搜索程序的当前路径 2. sys.path 提供的路径 包的相对导入: 包的相对导入是指包内模块的相互导入 相对导入时不能超出包的外部 包的相对导入 只对后两种导入方式有用 异常(基础)except: 什么是错误: 是指由于逻辑或语法等导程序无法正常执行的问题 什么是异常: 是程序出错的标识符的一种状态 当异常发时 程序不会再向下执行,而转去调用此函数的地方 待处理此错误并恢复为正常状态异常的作用: 用作信号, 通知上层调用者有错误产生需要处理 异常处理语句(4条): try-except 语句: 用于接受异常通知, 捕获异常 try-finally 语句: 执行必须执行的语句 raise 语句: 发送异常通知, 并进入异常状态 assert 语句: 根据条件选着性的发送 AssertionError类型的异常通知为什么要处理异常机制: 在程序调用层数比较深的时候, 向主调用函数传递错误信息 需要层层return返回 比较麻烦, 用异常处理机制可以较简单的传递错误信息 用<>括号表示的一定是对象 什么是迭代器 迭代器是访问可迭代对象的工具 迭代器是指用iter(obj) 函数返回的对象 迭代器可以用next(it) 函数获取可迭代对象的数据 迭代器只能向前取值,不会后退 用iter函数可以返回一个可迭代对象的迭代器 迭代器函数iter和nextiter(iterable) 从可迭代对象中返回一个迭代器,iterable 必须是能提供一个迭代器的对象next(iterator) 从迭代器iterator中获取下一个记录,如果无法获取下一条记录,则触发StopIteration异常 什么是生成器: 生成器是能够动态提供数据的对象,生成器对象也是可迭代对象 动态就是现用现生成数据 生成器有两种: 1. 生成器函数 2. 生成器表达式 生成器函数的定义 含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象 yield 翻译为(产生或生成) 动态生成数据 在函数内可以一个或多少 在生成器函数调用return 会触发一个StopIteration异常 函数: zip(iter1[, iter2[, ...]]) 返回一个zip对象,此对象用于生成元组,元组的个数由最小的可迭代对象决定 enumerate(iterable[, start]) 生成带索引的枚举对象,返回迭代类型为索引-值对(index-value对) , 默认索引从零开始,也可以用start指定(排序 自定义标号) 字节串和字节数组字节串bytes (也叫字节序列) 作用: 存储以字节为单位的数据 字节串是不可变的字节序列 字节: 字节是由8个位(bit)组成的数据单位,是计算机进行数据管理的单位 字节是用 0 ~ 255 范围内的整数表示的 2 ** 8 - 1 字节串的构造函数 bytes bytes() 生成一个空的字节串 等同于 b'' bytes(整数可迭代对象) # 用可迭代对象初始化一个字节串 bytes(整数n) 生成n个值为0的字节串 bytes(字符串, encoding='utf-8') 用字符串转为编码生成一个字节串 bytes 的运算: + += * *= < <= > >= == != in / not in 索引和切片 len(x) max(x) min(x) sum(x) any(x) all(x) bytes 和 str 的区别: bytes 存储字节( 通常值在 range(0, 256)) str 存储unicode字符( 通常值在0~65535) bytes 与 str 的转换 编码(encode) str ------------> bytes b = s.encode(encoding='utf-8') 解码(decode) bytes ----------> str s = b.decode(encoding='utf-8') 字节数组 bytearray 是可变的字节序列 字节数组的构造函数: bytearray bytearray() 创建空的字节数组 bytearray(整数) 用可迭代对象初始化一个字节数组 bytearray(整型可迭代对象) 生成n个值为0的字节数组 bytearray(字符串, encoding='utf-8') 用字符串的转换编码生成一个字节数组 索引和切片 (字节数组支持索引和切片的赋值操作,规则同列表的索引和切片赋值规则) bytearray的方法: BA.clear() 清空 BA.append(n) 追加一个字节(n为0~255的整数) BA.remove(value) 删除第一个出现的字节,如果没有出现,则触发ValueError错误 BA.reverse() 字节顺序反转 BA.decode(encoding='utf-8') # 解码为字符串 BA.find(sub[, start[,end]]) # 查找 sub

优秀的个人博客,低调大师

Python全栈工程师(每周总结:2)

ParisGabriel 感谢 大家的支持 每天坚持 一天一篇 点个订阅吧灰常感谢 当个死粉也阔以 week summer: Python人工智能从入门到精通 字符串 str # 不可变序列,只能存字符 列表 list # 可变的序列,可以存任意数据 元组 tuple # 不可变序列,可以存任意数据 字典dict # 可变无序,可以存任意数据 集合set #可变无序,只能存不可变数据 (可变就是id不变的情况下改变数据) 序列相关函数: len(x), max(x), min(x), sum(x), any(x), all(x) 序列有5种: star 字符串 list 列表 tuple 元组 bytes bytearray 列表 list: L = [ ] L = list() 创建函数 括号内放可迭代对象、可以空 L [ ] 括号内放下标 L [:: ] 第一个参数开始位置,第二个结束、第三个步长(步长决定方向) 列表推导式: [表达式 for 变量 in 可迭代对象](可以嵌套) del L[ ] 删除指定下表索引 列表可以索引下标 、切片 可以增、删、改、查 可以索引赋值、切片赋值(不是顺序切片时赋值一定要个数相等) 潜拷贝 浅拷贝是指在复制过程中,只复制一层变量,不会复制深层变量绑定的对象的复制过程 深拷贝 深拷贝通常只对可变对象进行复制,不可变对象通常不会复制 元组 type t = (1, ) 低于连个元素必须用, 号 t = type(x) 同列表一样 元组可以索引和切片和列表一样 但是但是不能赋值 T.index(v[, begin[, end]]) 返回对应元素的索引下标 T.count(x) 返回元组中对应的元素个数字典 dict: d = { } d = {“a”:1} 键值对形式存在 d[ ] 括号里放键 ,字典索引只索引键(key)索引赋值 : 只能修改值 ,存在修改 否者添加 dict() 生成一个字的字典 等同于 {} dict(iterable) 用可迭代对象初始化一个字典 dict(**kwargs) 用关键字传参形式创建一个字典 字典的键(key) 必须为不可变类型 且不能重复不可变类型:bool, int, float, complex, str, tuple, frozenset, bytes(后面再讲) in 在什么什么里面 not in 不在什么什么里面(判断键存在:只判断键) is 是 is not 不是 所有可迭代对象都可以用for 遍历 (字典只访问键)字典推导式 : d = {x : x ** 2 for x in range(10)} {键表达式 : 值表达式 for 变量 in 可迭代对象 if 真值表达式}(可嵌套) 字典 VS 列表 1. 都是可变对象 2. 索引方式不同,列表用整数索引,字典用键索引 3. 字典的插入,删除,修改数据的速度可能会快于列表(重要) 4. 列表的存储是有序的,字典的存储是无序的可变的数据类型有四种: list 列表、dict 字典 set 集合、bytearray 字节数组集合 set: s = set( ) s = set( ) 构造函数 数据不可重复 相当于只有键的字典 集合运算: & 生成两个集合的交集 | 生成两个集合的并集 - 生成两个集合的补集 ^ 生成两个集合的对称补集 > 判断一个集合是另一个集合的超集 < 判断一个集合是另一个集合的子集 (包含关系) == != 集合相同/不同 (与顺序无关)集合推导式:{表达式 for 变量 in 可迭代对象 [if 真值表达式]}(可嵌套)固定集合 frozenset: 固定集合是不可变的,无序的, 含有唯一元素的集合 (可以做字典键也可以做集合的值) frozenset() f = frozenset() 括号内放可迭代对象 相当于集合的全部方法(包括运算符)去掉修改集合的方法 常用字符串方法方法 说明S.isdigit() 判断字符串中的字符是否全为数字S.isalpha() 判断字符串是否全为英文字母S.islower() 判断字符串所有字符是否全为小写英文字母S.isupper() 判断字符串所有字符是否全为大写英文字母S.isspace() 判断字符串是否全为空白字符S.center(width[,fill]) 将原字符串居中,左右默认填充空格 width:所居中字符串的长度 fill:默认填充空格S.count(sub[, start[,end]]) 获取一个字符串中子串的个数 sub:所要获取的字符串 start:起始位置 end:结束位置S.find(sub[, start[,end]]) 获取字符串中子串sub的索引,失败返回-1 start:起始位置 end:结束位置S.strip() 返回去掉左右空白字符的字符串S.lstrip() 返回去掉左侧空白字符的字符串S.rstrip() 返回去掉右侧空白字符的字符串S.upper() 生成将英文转换为大写的字符串S.lower() 生成将英文转换为小写的字符串S.replace(old, new[, count]) 将原字符串的old用new代替,生成一个新的字符串 count:更换的次数S.startswith(prefix[, start[, end]]) 返回S是否是以prefix开头,如果以prefix开头返回True,否则返回False,S.endswith(suffix[, start[, end]]) 返回S是否是以suffix结尾,如果以suffix结尾返回True,否则返回False以下是不常用的 S.title() 生成每个英文单词的首字母大写字符串S.isnumeric() 判断字符串是否全为数字字符文本解析: S.split(sep=None) 拆分字符串 sep是拆分符号 S.join(iterable) S是分隔字符串 扩号内跟可迭代对象 列表的方法 :L.index(v [, begin[, end]]) 返回对应元素的索引下标, begin为开始索引,end为结束索引,当 value 不存在时触发ValueError错误L.insert(index, obj) 将某个元素插放到列表中指定的位置L.count(x) 返回列表中元素的个数L.remove(x) 从列表中删除第一次出现在列表中的值L.copy() 复制此列表(只复制一层,不会复制深层对象)L.append(x) 向列表中追加单个元素L.extend(lst) 向列表追加另一个列表L.clear() 清空列表,等同于 L[:] = []L.sort(reverse=False) 将列表中的元素进行排序,默认顺序按值的小到大的顺序排列L.reverse() 列表的反转,用来改变原列表的先后顺序L.pop([index]) 删除索引对应的元素,如果不加索引,默认删除最后元素,同时返回删除元素的引用关系 字典的方法 D代表字典对象 D.clear() 清空字典D.pop(key) 移除键,同时返回此键所对应的值D.copy() 返回字典D的副本,只复制一层(浅拷贝)D.update(D2) 将字典 D2 合并到D中,如果键相同,则此键的值取D2的值作为新值D.get(key, default) 返回键key所对应的值,如果没有此键,则返回defaultD.keys() 返回可迭代的 dict_keys 集合对象D.values() 返回可迭代的 dict_values 值对象D.items() 返回可迭代的 dict_items 对象 Python3 集合的方法: 方法 意义S.add(e) 在集合中添加一个新的元素e;如果元素已经存在,则不添加S.remove(e) 从集合中删除一个元素,如果元素不存在于集合中,则会产生一个KeyError错误S.discard(e) 从集合S中移除一个元素e,在元素e不存在时什么都不做;S.clear() 清空集合内的所有元素S.copy() 将集合进行一次浅拷贝S.pop() 从集合S中删除一个随机元素;如果此集合为空,则引发KeyError异常S.update(s2) 用 S与s2得到的全集更新变量SS.difference(s2) 用S - s2 运算,返回存在于在S中,但不在s2中的所有元素的集合S.difference_update(s2) 等同于 S = S - s2S.intersection(s2) 等同于 S & s2S.intersection_update(s2) 等同于S = S & s2S.isdisjoint(s2) 如果S与s2交集为空返回True,非空则返回FalseS.issubset(s2) 如果S与s2交集为非空返回True,空则返回FalseS.issuperset(...) 如果S为s2的子集返回True,否则返回FalseS.symmetric_difference(s2) 返回对称补集,等同于 S ^ s2S.symmetric_difference_update(s2) 用 S 与 s2 的对称补集更新 SS.union(s2) 生成 S 与 s2的全集 Python运算符优先级 运算符 描述(), [], {key: value}, {} 元组表达式、列表表达式、字典表达式、集合表达式x[index], x[index:index],x(arguments...), x.attribute 索引,切片,函数调用,属性引用** 指数 (最高优先级)~, +, - 按位翻转, 正号,负号*, /, %, // 乘,除,取模和地板除+, - 加法, 减法>>, << 右移, 左移运算符& 位与(AND)^ 位异或(XOR)| 位或(OR)<=, <, >, >=, ==, !=,is, is not, in, not in 比较,身份测试,成员资格测试not 布尔非and 布尔与or 布尔或if - else 条件表达式lambda lambda表达式 数据类型: 数值类型: int, float, complex, bool容器: 不可变的容器 str, tuple, frozenset, bytes(字节串) 可变的容器 list, dict, set, bytearray(字节数组)值: None, False, True 运算符 算术运算符 + - * / // % ** 比较运算符: < <= > >= == != in / not in is, is not 布尔运算: not, and, or +(正号) -(负号) & | ^ [] (索引,切片,键索引) 表达式: 1 1 + 2 max(1,2,3) # 函数调用是表达式 x if x > y else y, 条件表达式 三种推导式: 列表,字典,集合推导式(三种) 语句: 表达式语句: 所有的表达式都可以单独写在一行,形成一个语句,例: print("hello world") 1 + 2 赋值语句: a = 100 a = b = c = 100 x, y = 100, 200 a[0] = 100 dict['name'] = 'tarena' del 语句 if 语句 while 语句 for 语句 break 语句 continue语句 pass 语句 内建函数: len(x), max(x), min(x), sum(x), any(x), all(x)构造函数(用来创建同类型的数据对象) bool(x), int(x), float(x), complex(x), list(x), tuple(x), str(x), dict(x), set(x), frozenset(x) abs(x) round(x) pow(x, y, z=None) bin(x), oct(x), hex(x) chr(x), ord(x) range(start, stop, step) input(x), print(x) >>> help(__builtins__) 函数: 就是把语句块封装起来 形成一个语句块 利用函数变量直接调用语句块的方式 用户自定义级别的函数是为了提高代码的可用性 重用性 以及逻辑清晰 维护方便 (def 函数名(形参列表):冒号) 形参列表可以为空 函数是一个空间,空间内变量不重复就不会冲突 函数调用: 函数名(实参) return语句 用于返回非None对象语句 函数的参数传递: 传参方式:(2种) 位置传参(包含关系 ) 序列传参 关键字传参(包含关系) 字典关键字传参位置传参: 实参与形参的位置要对应序列传参: 用 * 将序列拆解 然后位置传参关键字传参 将字典用“**”拆解后 实参和形参必须按形参名复制 拆解后键名要在形参中存在必须一致 键名必须是字符串且标识符综合传参: 在能确定形参能唯一匹配到相应实参的情况下 所有传参方式可以任意组合 位置传参(序列传参)一定要在关键字传参(字典关键字传参)的左侧函数的缺省参数: 缺省参数必须从右至左依次存在的命名关键字形参: 语法: def 函数名(*, 命名关键字形参): 语句块 或 ef 函数名(*args, 命名关键字形参): 语句块 (关键字形参 必须用关键字传参) 作用: 收集多余关键字传参双星号字典传参: 语法: def 函数名(**字典形参名): 语句块 作用: 强制所有的参数都参数都必须用关键字传参或字典关键字传参函数的参数说明: 位置形参、星号元组形参、命名关键字形参、双星号字典形参可以混合使用函数自左到右的顺序为: 1.位置形参 2.星号元组形参 3.命名关键字形参 4.双星号字典形参 全局变量:global variable: 函数外,模块内的变量 全局变量所有函数都可以直接访问局部变量:local variable: 函数内的变量 调用时才被创建,在函数调用之后销毁传参的排序规则: 从左到右 1.位置形参 2.星号元组形参 3.命名关键字形参 4.双星号字典形参 函数: globals()/locals() globals()返回当前全局作用域内变量的字典 locals() 返回当前局部作用域内变量的字典 函数名是变量 创建时绑定函数 函数的变量名可以序列交换算法 函数可以作为另一个函数的实参 函数可以作为另一个函数返回值 函数可以嵌套python的4个作用域: 作用域: 英文解释 缩写 局部作用域(函数内) Local(function) L 外部嵌套函数作用域 Enclosing functio loc E 函数定义所在模块(文件)作用域 Global(module) G python内建模块作用域 Builtin(python) B 包含关系(内建>模块>外部嵌套函数>函数内)变量名查找规则: 访问变量时,先查找本地变量,然后是包裹此函数外的函数内部的变量 ,之后是全局变量,最后是内建变量 L ---> E ---> G ---> B 在默认情况下,变量名赋值会创建或者改变当前作用域的变量global语句: 声明一个全局变量nonlocal语句: 外部嵌套函数变量 调用不可修改外部嵌套函数作用域内的变量进行操作lambda表达式: 创建一个匿名函数对象 lambda[ 参数1, 参数...]: 表达式 函数: eval () / exec() 函数 eval(srouce,globals=None, locals=None) 把一个字符串srouce 当成一个表达式来执行,返回表达式结果 eval(source, globals=None, local=None) 把一个字符串 srouce 当成一个表达式来执行,返回表达式执行的结果 exec(source, globals=None, locals=None) 把一个字符串source 当成程序来执行 全部划重点 加粗 加长 加大 溜了 不吹NB了....

优秀的个人博客,低调大师

Python全栈工程师(每周总结:1)

ParisGabriel python今年9月份将被国家纳入计算机二级资格证 先学就是鼻祖 几年后你就是大牛 Python人工智能从入门到精通 week summer: 数字(整型int,浮点数float,复数complex,布尔型bool)字符串str 列表list 等bool(true=1、false=0)None 空值算数运算符:+ - * / // ** % 优先级:(), [], {key: value}, {} 元组表达式、列表表达式、字典表达式、集合表达式x[index], x[index:index],x(arguments...), x.attribute 索引,切片,函数调用,属性引用** 指数 (最高优先级)~, +, - 按位翻转, 正号,负号*, /, %, // 乘,除,取模和地板除+, - 加法, 减法>>, << 右移, 左移运算符& 位与(AND)^ 位异或(XOR)| 位或(OR)<=, <, >, >=, ==, !=, is, is not, in, not in 比较,身份测试,成员资格测试not 布尔非and 布尔与or 布尔或if - else 条件表达式lambda lambda 表达式变量命名:必须以字母或下划线开头(驼峰法则)序列赋值:a,b,c = 100, 200, 300变量交换:a,b = 200,100del 删除变量help(“__main__”) 查看变量 Q退出内存自动管理方式:引用计数is/is not 判断是否为同一个对象id(obj)函数: 返回对象在内纯中的id小整数对象值:-5 ~ 256比较运算符:< <= > >= == != 数值对象的构造函数:float(obj) 字符串转换浮点数 int 转换整数complex(r,i) 创建复数bool(true/false) 创建布尔值bool(obj) 所有0或 空值都会返回falseabs(x) 取x绝对值round(number,ndigits) 四舍五入 ndigits小数点个数(可以是负数:反向取整)help(函数对象) 函数或查看详细帮助“\” 折行符() [ ] {} 隐式折行符 sep 两个值之间的分隔符默认空格print(sep = “”,end = “”){ end行位默认换行符not 布尔非or 布尔或 { 短路运算and 布尔与+ 表达式只有一个数据参加(一元运算符)- 表达式 如:a = 5 ,b = -a ,c = +a转移符:\' 单引号\" 双引号\\ 单反斜杠\n 换行\r 返回光标至行首\t 水平制表符\v 垂直制表符\f 换页\b 倒退\0 空字符,字符值为0\xXX XX为两位16进制表示的自符\uXXXX XXXX为4个16进制的Unicode16字符\UXXXXXXXX 8个16进制表示的Unicode32字符man ASCII 查看帮助文档命令常用ASCII编码:字符 十进制 十六进制 0 48 0x30 A 65 0x41 a 97 0x61len() 返回字符串的个数raw 让转义符无效(原始字符)(r“hello world”)+= *= 与其他符合运算符相同in/not in 判断字符串是存在字符串的比较运算:> >= < <= == != 依次按照编码进行比较,直到最短字符串结束为止s[int] 索引 index Python的字符串是不可以改变字符序列的Python序列都可以用索引来访问序列中的对象Python的序列正向索引是从0开始的最后一个索引为len(s)-1Python序列的反向索引是从-1开始的 -1是最后一个 第一个是 -len(s)切片 slice :s[(开始索引b):(结束索引e):(步长s)] 步长等于偏移量默认1 索引从0开始 顾头不顾尾 步长为负时反向切片(步长决定方向)python3 中常用函数;len (s) 返回序列长度max(s) 返回序列最大值元素min(s) 返回序列最小值元素ord(a) 返回一个字符的Unicode值(10进制)chr(i) 返回一个整数的Unicode字符bin(i) 将整数转换为二进制字符串oct(i) 将整数转换为八进制字符串hex(i) 将整数转换为十六进制字符串常用的字符串方法:文档参见:对象.方法名(方法传参)"abc".isalpha() # 语法是对的123.isalpha() # 语法是错的方法 说明S.isdigit() 判断字符串中的字符是否全为数字S.isalpha() 判断字符串是否全为英文字母S.islower() 判断字符串所有字符是否全为小写英文字母S.isupper() 判断字符串所有字符是否全为大写英文字母S.isspace() 判断字符串是否全为空白字符S.center(width[,fill]) 将原字符串居中,左右默认填充空格 width:所居中字符串的长度 fill:默认填充空格S.count(sub[, start[,end]]) 获取一个字符串中子串的个数 sub:所要获取的字符串 start:起始位置 end:结束位置S.find(sub[, start[,end]]) 获取字符串中子串sub的索引,失败返回-1start:起始位置 end:结束位置S.strip() 返回去掉左右空白字符的字符串S.lstrip() 返回去掉左侧空白字符的字符串S.rstrip() 返回去掉右侧空白字符的字符串S.upper() 生成将英文转换为大写的字符串S.lower() 生成将英文转换为小写的字符串S.replace(old, new[, count]) 将原字符串的old用new代替,生成一个新的字符串 count:更换的次数S.startswith(prefix[, start[, end]]) 返回S是否是以prefix开头,如果以prefix开头返回True,否则返回False,S.endswith(suffix[, start[, end]]) 返回S是否是以suffix结尾,如果以suffix结尾返回True,否则返回False以下是不常用的 S.title() 生成每个英文单词的首字母大写字符串S.isnumeric() 判断字符串是否全为数字字符ASCII 用8个位表示 最高位一定是0Unicode用16位表示 最高位也一定是0占位符和其的类型码:%s 字符串 使用shr(obj)转为字符串%r 字符串 使用repr(obj)转为字符串%c 整数转为字符串,使用chr(i)函数%d 10进制整数%o 8进制整数%x 16进制整数(字符a-f)%X 16进制整数(字符A-F)%e 浮点数(e)如 2.9e+10%E 浮点数(E)如2.9E+10%f %F 浮点数10进制形式%g %G 进制进形式浮点数或指浮点数自动转换%% 等同于一个 % 字符 占位符与类型码之间的格式语法:%[- + 0 宽度.精度]类型码- 左对齐+ 右对齐0 左右空白位置补0宽度:整个数据输出的宽度精度:保留小数点后多少位,默认6位可迭代对象包括:字符串 str 列表 list元组 tuple字典 dictrange()函数: 可迭代对象创建 也叫整数序列生成器 (顾头不顾尾)列表 list:(列表的id是不可变的 除非重新定义)列表是一种容器(通常用来储存计算机的数据对象)列表是可以被改变的序列是由一系列特定元素组成的 元素与元素之间可能没有任何关联关系但他们有先后顺序关系列表的运算:+ 用于拼接列表+= 用于将右侧的可迭代对象的数据追加到原列表中* 用于生成重复列表*= L * = 2 (L = L * 2)列表的比较运算:< <= > >= == !=比较规则和字符串完全相同列表的in、notin:判断一个元素是否存在于列表中 如果纯在返true否则falsein 和 nat in 返回值相反(只能判断列表元素 不能判断元素内字符) week summerkey word: print: print(“hello world”) 输出打印语句 input: input(“plaese input :”) 输入函数 提示可以为空 if : if 1 >2 : print("1>2") elif 1>3: print("1>3") else: print("1<2") if:如果 else:否则 elif:否者如果 (单if不加else:如果真) while: i = 0 while i < 5: print(i) i += 1 else: print("6") i:循环变量 while可以加或不加else 条件不成时立执行else若条件成立 循环结束后将继续执行else for: for x in ramge(10): print(x) else: print(11) x:循环取出可迭代对象的值 for可以加或不加else 条件不成时立执行else若条件成立 循环结束后将继续执行else 死循环: while True; a = int(input()) print("123") if a = “” break 死循环: 无限循环 配合break跳出循环死循环不能加else break 终止循环一般配合if语句使用 终止循环 若循环套用是只会在本循环作用域有效不影响外部循环 若break跳出循环 else将不再执行continue 跳过本次循环一般配合if语句使用 跳过本次循环 若循环套用是只会在本循环作用域有效不影响外部循环 continue 用法需注意 细节不当将形成死循环复合语句的嵌套: for x in range(10) for y in range(5) print(x , y) if x == 10: break else: for x in range(50) print(x) i = 0 while i < 10: peint(i) x = 0 while x < 10: print(x) if i == 10: break else: while i <10: print(i * i) if a > 5: if a < 10: peint(a) else: if a > 0 : print(a) else: print(a) if while for 可以任意嵌套配合使用

优秀的个人博客,低调大师

Python全栈工程师(while、占位符)

ParisGabriel Python 入门基础 UnicodeASCII 用8个位表示文字 ,最高位一定是零,低七位表示数值Unicode是由16个位组成的(65535) 最高位也是0x0000~0xfffhelp(str) 查看所有str函数 字符串的格式化表达式:生成一定格式的字符串格式字符串中以 % 开头的为占位符,占位符的位置将参数值替换语法:格式字符串 % 参数值格式字符串 % (参数值1,参数值2,...)占位符和其的类型码:%s 字符串 使用shr(obj)转为字符串%r 字符串 使用repr(obj)转为字符串%c 整数转为字符串,使用chr(i)函数%d 10进制整数%o 8进制整数%x 16进制整数(字符a-f)%X 16进制整数(字符A-F)%e 浮点数(e)如 2.9e+10%E 浮点数(E)如2.9E+10%f %F 浮点数10进制形式%g %G 进制进形式浮点数或指浮点数自动转换%% 等同于一个 % 字符 占位符与类型码之间的格式语法:%[- + 0 宽度.精度]类型码- 左对齐+ 右对齐0 左右空白位置补0 宽度:整个数据输出的宽度精度:保留小数点后多少位,默认6位"%10d" %123 #" 123""%+10d"%123 #" +123""%-10d"%123 #"123 ""%10s"%"abc" #" abc""%010d"%123 #"0000000123" "%f"%3.14159625358 # "3.141593""%7.2f"%3.14159265358#" 3.14" 循环语句:while:根据一定的条件,重复执行一些相同或相似的内容先判断真值表达式是否成立在执行执行完内容继续返回真值表达式判断是否成立 直到真值表达式为false时 判断是否有else有则执行else的内容没有则循环结束注意事项:要控制真值表达式的值来防止死循环通常用真值表达式内的循环变量来控制真值表达式的值通常在循环语句块内改变循环变量来控制循环次数和变量走向while的嵌套:while语句和其他语句一样,可以嵌套放入任何复合语句当中break:用于循环语句(while、for)中用来终止当前循环(跳出循环)当break语句执行后此循环以后的语句将不再执行break终止循环时 else语句块将不再执行break语句通常和if组合使用break只能终止当前作用域 如循环嵌套时,不会跳出外循环break只能在循环语句(while、for)内使用死循环:死循环是指循环条件一直成立的循环死循环通常用break语句来终止循环死循环的else语句块永远不会执行 练习:1.输入一行字符串,将字符串中Unicode编码值最大的一个字符打印出来(不允许用max函数)提示:while内可以嵌套if 答案: print("Answer to question 1:", "\n") s = input("plaese input at will string:") i = 0 top = s[0] while i < len(s): if ord(top) < ord(s[i]): top = s[i] i += 1 print("you input string in top1:", top, ord(top)) 2.打印 从零开始的浮点数,每个数增加0.5,打印出10以内的这样的数:0.00.51.00.52.0...10 答案: print("Answer to question 2:", "\n") i = 0 while i < 10: i += 0.5 print(i) 3.打印输出1~20在同一行内 结束后换行 答案: s = 0 while s < 20: s += 1 print(s, end = " ") else: print() 4.打印输出1~20在同一行内 打印10行 i = 0 while i < 10: s = 0 while s < 20: s += 1 print(s, end = " ") else: print() i += 1 5.当输入一些数字,输入负数时结束输入当完成输入完后,打印输入的数时多少 答案: s = 0 while True: a = int(input("plaese input at will integer:")) s += a if a < 0: break print(s) 6.Sn = 1/2+1/4+1/8....+1/(2**n)求当n等同于100时Sn的值是多少 答案: Sn = 1 i = 0 while i < 100: i += 1 Sn += 1 / 2 ** i print(Sn) 7.输入一个整数打印出矩形 若输入1则输出1个# 例如: 输入1:# 输入2:#### 输入6:####### ## ## ## ## ####### 答案: s = int(input("plaese input at will integer:")) if s > 1: print("#" * s) i = 2 while i < s: i += 1 print("#" + " " * (s - 2) + "#") print("#" * s) else: print("#") 8.用while语句实现打印三角形,输入一个整数表示三角形的宽度和高度,打印出相应的三角形如:1)**********2)******* ** *3) * *********4)********** 答案: a = int(input("plaese input at will ingeger:")) i = 0 b = a c = a d = a while i < a: i += 1 print("*" * i) print() i = 0 while i < d: print((a - d) * " " + "*" * d) d -= 1 print() i = 0 while i < c: i += 1 print((c - i) * " " + "*" * i) print() i = 0 while i < b: print("*" * b) b -= 1 a = int(input("plaese input at will ingeger:")) i = 0 d = a while i < a: while i < d: print((a - d) * " " + "*" * d) d -= 1 print("*" * (i + 1)) i += 1 print()

优秀的个人博客,低调大师

Python全栈工程师(运算符、if)

ParisGabriel Python 入门基础 比较运算符:< 小于<= 小于等于> 大于>= 大于等于== 等于!= 不等于 语法: 表达式1>表达式2 返回布尔类型 数值对象的构造函数: float(obj) 用字符串或数字转换为浮点数,如果不给出实参,则返回0.0 int(x=0,base=10) 用数字或者字符串转换为整数,如果不给出实参,则返回0.0 bas表示是进制 complex(r=0.0,i=0.0) 用数字创建一个复数 bool(x) 用x创建一个布尔值(true/false) bool(obj)返回假值的情况:None 空值false 假值00.00j所有的数字零‘’ 空字符串[ ] 空列表{ }空词典() 空原组... 函数调用表达式:函数名(传参列表)说明:函数调用表达式时,此表达式一定是会返回一个对象的引用关系如果不需要返回值时,通常返回none对象的引用关系 内建数值型函数:abs(x) 取x的绝对值 round(number,ndigits=0) 对数值进行四舍五入 ,ndigits是小数向右取整的位数,负数表示像左取整 pow(x,y,z=none) 相当于x**y或x**y%z help()查看帮助 help(函数或对象名) help(int) 语句: 语句是由一些表达式组成,通常一条一句可以独立执行来完成一部分事情并形成结果Python建议一条语句写在一行内多条一句子写在一行内需要用“;”分开 print("hello") x = 100 + 200 print(x) print("hello"); x = 100 + 200; print(x) 显示换行:折行符“\”折行符必须一行的末尾,来告诉解释执行器下一行也是本行的语句 隐式折行符:所有的括号的内容换行,成为隐式折行符()、{}、[] 函数的使用:基本输入函数input从标准输入设备上读取一个字符串(末尾的换行符会被删除)返回输入的字符串(仅Python3) 提示字符可以为空 基本输出函数:print将一系列的值一字符串的形式输出到标准输出设备上,默认为终端选项的关键字参数:sep:两个值之间的分隔符,默认为一个空格end:输出完毕后在末尾自动加一个字符串,默认为换行符(\n) 练习:1.输入两个整数,分别用变量x,y绑定1)打印输出计算这两个数的和2)打印输出计算这两个数的积3)打印输出计x的y次方 答案: x = int(input("plwase input integer:")) y = int(input("plwase input integer:")) print(x + y, "\n", x * y, "\n", x ** y) 2.今天是小明的20岁生日,假设每年都有365天,计算他过了多少个星期天,剩余多少天 答案: print((20 * 365) // 7, "星期天 剩余", (20 * 365) % 7, "天") 3.本别输入当前时间的时、分、秒 在终端打印输出当前距离0:0:0过了多少少天 答案: h = int(input("plwase input hour:")) m = int(input("plwase input minute:")) s = int(input("plwase input second:")) print(h * 3600 + m * 60 + s, "second") if语句: 让程序根据条件选着性的执行某条语句或某些语句 语法: a = int(input("plaese input integer:")) if a > 0: print(a, ">0") elif a > 6: print(a, ">6") elif a > 100: print(a, ">100") else: print(a, "<0") elif可以有0个或多个else可以有零个或1个 并且所有语句当中只能执行一个 if的嵌套:if语句本身是由多条子句组成的一条复合语句if语句可以作为语句嵌套到另一个语句内部 条件表达式:表达式1 if 真值表达式 else 表达式2根据真值表达式的取值(true、false)来决定执行表达式1或2,并返回结果 money = int(input("100")) pay = money - 20 if money >= 100 else money pass语句:通常用来填充语法空白又名空语句 布尔运算符:not and or布尔非 not如果为true返回false否则为反布尔或 or优先返回真值见true得true 布尔与 and优先返回假值对象见false得false 正负号运算符:+ 表达式- 表达式这是一个一元运算符(只有一个数据参加运算) 练习:1.北京出租车价格 3公里以内13元基本单价:2.3元/公里(超出3公里以外)回空费:超过15公里 每公里 加收单价的50%的会空费(3.45元/公里)输入公里数 打印费用金额 答案: kilometre = int(input("plaese input kilometre:")) if kilometre < 0: if kilometre > 15: money = (kilometre - 15) * 3.45 + (15 - 3) + 13 print("money:", money, "$") elif 3 < kilometre < 15: money = (kilometre - 3) * 2.3 + 13 print("money:", money, "$") else: print("money:13$") else: print("not'is kilonetre") 2.输入一个学生的三科成绩(3个整数:打印出最高分、最低分、平局分是多少 答案: a = int(input("plaese input english mark:")) b = int(input("plaese input language mark:")) c = int(input("plaese input mathematisc mark:")) if 100 > a > 0 and 100 > b > 0 and 100 > c > 0: if a > b and a > c: print("top score english:", a) elif b > c and b > a: print("top score language:", b) elif c > a and c > b: print("top score mathematisc:", c) if a < b and a < c: print("lowest english:", a) elif b < c and b < a: print("lowest language:", b) elif c < a and c < b: print("lowest mathematisc:", c) print("mean:", (a + b + c)/3) else: print("not'is mark") 3.bmi指数(body、mass、index)以称身体质量指数bmi的计算公式: bmi = 体重(公斤)/身高的平方标准表: bmi< 18.5 体重过轻18.5<=bmi<24 体重正常bmi> 24 体重过重输入公斤体重、身高 打印出 bmi的值 并打印体重状况 答案: z = int(input("plaese input your weigh:")) g = float(input("plaese input your height:")) if z < 0 and g < 0: bim = (z / g) ** 2 if bim < 18.5: print("your bim qing") elif 24 > bim > 18.5: print("your bim normal") else: print("your bim serious") else: print("your inuput error")

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册