diff --git a/assets/adjectives.txt b/assets/adjectives.txt new file mode 100644 index 0000000..81f7688 --- /dev/null +++ b/assets/adjectives.txt @@ -0,0 +1,1896 @@ +aback +abaft +abandoned +abashed +aberrant +abhorrent +abiding +abject +ablaze +able +abnormal +aboard +aboriginal +abortive +abounding +abrasive +abrupt +absent +absolute +absorbed +absorbing +abstracted +absurd +abundant +abusive +academic +acceptable +accessible +accidental +acclaimed +accomplished +accurate +aching +acid +acidic +acoustic +acrid +acrobatic +active +actual +actually +ad hoc +adamant +adaptable +addicted +adept +adhesive +adjoining +admirable +admired +adolescent +adorable +adored +advanced +adventurous +affectionate +afraid +aged +aggravating +aggressive +agile +agitated +agonizing +agreeable +ahead +ajar +alarmed +alarming +alcoholic +alert +alienated +alike +alive +all +alleged +alluring +aloof +altruistic +amazing +ambiguous +ambitious +amiable +ample +amuck +amused +amusing +anchored +ancient +ancient +angelic +angry +angry +anguished +animated +annoyed +annoying +annual +another +antique +antsy +anxious +any +apathetic +appetizing +apprehensive +appropriate +apt +aquatic +arctic +arid +aromatic +arrogant +artistic +ashamed +aspiring +assorted +assured +astonishing +athletic +attached +attentive +attractive +auspicious +austere +authentic +authorized +automatic +available +avaricious +average +awake +aware +awesome +awful +awkward +axiomatic +babyish +back +bad +baggy +barbarous +bare +barren +bashful +basic +batty +bawdy +beautiful +beefy +befitting +belated +belligerent +beloved +beneficial +bent +berserk +best +better +bewildered +bewitched +big +big-hearted +billowy +biodegradable +bite-sized +biting +bitter +bizarre +black +black-and-white +bland +blank +blaring +bleak +blind +blissful +blond +bloody +blue +blue-eyed +blushing +bogus +boiling +bold +bony +boorish +bored +boring +bossy +both +bouncy +boundless +bountiful +bowed +brainy +brash +brave +brawny +breakable +breezy +brief +bright +brilliant +brisk +broad +broken +bronze +brown +bruised +bubbly +bulky +bumpy +buoyant +burdensome +burly +bustling +busy +buttery +buzzing +cagey +calculating +callous +calm +candid +canine +capable +capital +capricious +carefree +careful +careless +caring +cautious +cavernous +ceaseless +celebrated +certain +changeable +charming +cheap +cheeky +cheerful +cheery +chemical +chief +childlike +chilly +chivalrous +chubby +chunky +circular +clammy +classic +classy +clean +clear +clear-cut +clever +cloistered +close +closed +cloudy +clueless +clumsy +cluttered +coarse +coherent +cold +colorful +colorless +colossal +colossal +combative +comfortable +common +compassionate +competent +complete +complex +complicated +composed +concerned +concrete +condemned +condescending +confused +conscious +considerate +constant +contemplative +content +conventional +convincing +convoluted +cooing +cooked +cool +cooperative +coordinated +corny +corrupt +costly +courageous +courteous +cowardly +crabby +crafty +craven +crazy +creamy +creative +creepy +criminal +crisp +critical +crooked +crowded +cruel +crushing +cuddly +cultivated +cultured +cumbersome +curious +curly +curved +curvy +cut +cute +cylindrical +cynical +daffy +daily +damaged +damaging +damp +dangerous +dapper +dapper +daring +dark +darling +dashing +dazzling +dead +deadly +deadpan +deafening +dear +dearest +debonair +decayed +deceitful +decent +decimal +decisive +decorous +deep +deeply +defeated +defective +defenseless +defensive +defiant +deficient +definite +delayed +delectable +delicate +delicious +delightful +delirious +demanding +demonic +dense +dental +dependable +dependent +depraved +depressed +deranged +descriptive +deserted +despicable +detailed +determined +devilish +devoted +didactic +different +difficult +digital +dilapidated +diligent +dim +diminutive +dimpled +dimwitted +direct +direful +dirty +disagreeable +disastrous +discreet +discrete +disfigured +disguised +disgusted +disgusting +dishonest +disillusioned +disloyal +dismal +dispensable +distant +distinct +distorted +distraught +distressed +disturbed +divergent +dizzy +domineering +dopey +doting +double +doubtful +downright +drab +draconian +drafty +drained +dramatic +dreary +droopy +drunk +dry +dual +dull +dull +dusty +dutiful +dynamic +dysfunctional +each +eager +early +earnest +earsplitting +earthy +easy +easy-going +eatable +economic +ecstatic +edible +educated +efficacious +efficient +eight +elaborate +elastic +elated +elderly +electric +elegant +elementary +elfin +elite +elliptical +emaciated +embarrassed +embellished +eminent +emotional +empty +enchanted +enchanting +encouraging +endurable +energetic +enlightened +enormous +enraged +entertaining +enthusiastic +entire +envious +envious +equable +equal +equatorial +erect +erratic +essential +esteemed +ethereal +ethical +euphoric +evanescent +evasive +even +evergreen +everlasting +every +evil +exalted +exasperated +excellent +excitable +excited +exciting +exclusive +exemplary +exhausted +exhilarated +exotic +expensive +experienced +expert +extensive +extra-large +extraneous +extra-small +extroverted +exuberant +exultant +fabulous +faded +failing +faint +fair +faithful +fake +fallacious +false +familiar +famous +fanatical +fancy +fantastic +far +faraway +far-flung +far-off +fascinated +fast +fat +fatal +fatherly +faulty +favorable +favorite +fearful +fearless +feeble +feigned +feisty +feline +female +feminine +fertile +festive +few +fickle +fierce +filthy +fine +finicky +finished +firm +first +firsthand +fitting +five +fixed +flagrant +flaky +flamboyant +flashy +flat +flawed +flawless +flickering +flimsy +flippant +floppy +flowery +flufy +fluid +flustered +fluttering +foamy +focused +fond +foolhardy +foolish +forceful +foregoing +forgetful +forked +formal +forsaken +forthright +fortunate +four +fragile +fragrant +frail +frank +frantic +frayed +free +freezing +French +frequent +fresh +fretful +friendly +frightened +frightening +frigid +frilly +frivolous +frizzy +front +frosty +frothy +frozen +frugal +fruitful +frustrating +full +fumbling +fumbling +functional +funny +furry +furtive +fussy +future +futuristic +fuzzy +gabby +gainful +gamy +gaping +gargantuan +garrulous +gaseous +gaudy +general +general +generous +gentle +genuine +ghastly +giant +giddy +gifted +gigantic +giving +glamorous +glaring +glass +gleaming +gleeful +glib +glistening +glittering +gloomy +glorious +glossy +glum +godly +golden +good +good-natured +goofy +gorgeous +graceful +gracious +grand +grandiose +grandiose +granular +grateful +gratis +grave +gray +greasy +great +greedy +green +gregarious +grey +grieving +grim +grimy +gripping +grizzled +groovy +gross +grotesque +grouchy +grounded +growing +growling +grown +grubby +gruesome +grumpy +guarded +guiltless +guilty +gullible +gummy +gusty +guttural +habitual +hairy +half +half +hallowed +halting +handmade +handsome +handsomely +handy +hanging +hapless +happy +happy-go-lucky +hard +hard-to-find +harebrained +harmful +harmless +harmonious +harsh +hasty +hateful +haunting +heady +healthy +heartbreaking +heartfelt +hearty +heavenly +heavy +hefty +hellish +helpful +helpless +hesitant +hidden +hideous +high +highfalutin +high-level +high-pitched +hilarious +hissing +historical +hoarse +holistic +hollow +homeless +homely +honest +honorable +honored +hopeful +horrible +horrific +hospitable +hot +huge +hulking +humble +humdrum +humiliating +humming +humongous +humorous +hungry +hurried +hurt +hurtful +hushed +husky +hypnotic +hysterical +icky +icy +ideal +ideal +idealistic +identical +idiotic +idle +idolized +ignorant +ill +illegal +ill-fated +ill-informed +illiterate +illustrious +imaginary +imaginative +immaculate +immaterial +immediate +immense +imminent +impartial +impassioned +impeccable +imperfect +imperturbable +impish +impolite +important +imported +impossible +impractical +impressionable +impressive +improbable +impure +inborn +incandescent +incomparable +incompatible +incompetent +incomplete +inconclusive +inconsequential +incredible +indelible +indolent +industrious +inexpensive +inexperienced +infamous +infantile +infatuated +inferior +infinite +informal +innate +innocent +inquisitive +insecure +insidious +insignificant +insistent +instinctive +instructive +insubstantial +intelligent +intent +intentional +interesting +internal +international +intrepid +intrigued +invincible +irate +ironclad +irresponsible +irritable +irritating +itchy +jaded +jagged +jam-packed +jaunty +jazzy +jealous +jittery +jobless +joint +jolly +jovial +joyful +joyous +jubilant +judicious +juicy +jumbled +jumbo +jumpy +jumpy +junior +juvenile +kaleidoscopic +kaput +keen +key +kind +kindhearted +kindly +klutzy +knobby +knotty +knowing +knowledgeable +known +kooky +kosher +labored +lackadaisical +lacking +lame +lame +lamentable +languid +lanky +large +last +lasting +late +laughable +lavish +lawful +lazy +leading +leafy +lean +learned +left +legal +legitimate +lethal +level +lewd +light +lighthearted +likable +like +likeable +likely +limited +limp +limping +linear +lined +liquid +literate +little +live +lively +livid +living +loathsome +lone +lonely +long +longing +long-term +loose +lopsided +lost +loud +loutish +lovable +lovely +loving +low +lowly +loyal +lucky +ludicrous +lumbering +luminous +lumpy +lush +lustrous +luxuriant +luxurious +lying +lyrical +macabre +macho +mad +maddening +made-up +madly +magenta +magical +magnificent +majestic +major +makeshift +male +malicious +mammoth +maniacal +many +marked +married +marvelous +masculine +massive +material +materialistic +mature +meager +mealy +mean +measly +meaty +medical +mediocre +medium +meek +melancholy +mellow +melodic +melted +memorable +menacing +merciful +mere +merry +messy +metallic +mighty +mild +military +milky +mindless +miniature +minor +minty +minute +miscreant +miserable +miserly +misguided +mistaken +misty +mixed +moaning +modern +modest +moist +moldy +momentous +monstrous +monthly +monumental +moody +moral +mortified +motherly +motionless +mountainous +muddled +muddy +muffled +multicolored +mundane +mundane +murky +mushy +musty +mute +muted +mysterious +naive +nappy +narrow +nasty +natural +naughty +nauseating +nautical +near +neat +nebulous +necessary +needless +needy +negative +neglected +negligible +neighboring +neighborly +nervous +nervous +new +next +nice +nice +nifty +nimble +nine +nippy +nocturnal +noiseless +noisy +nonchalant +nondescript +nonsensical +nonstop +normal +nostalgic +nosy +notable +noted +noteworthy +novel +noxious +null +numb +numberless +numerous +nutritious +nutty +oafish +obedient +obeisant +obese +oblivious +oblong +obnoxious +obscene +obsequious +observant +obsolete +obtainable +obvious +occasional +oceanic +odd +oddball +offbeat +offensive +official +oily +old +old-fashioned +omniscient +one +onerous +only +open +opposite +optimal +optimistic +opulent +orange +orderly +ordinary +organic +original +ornate +ornery +ossified +other +our +outgoing +outlandish +outlying +outrageous +outstanding +oval +overconfident +overcooked +overdue +overjoyed +overlooked +overrated +overt +overwrought +painful +painstaking +palatable +pale +paltry +panicky +panoramic +parallel +parched +parsimonious +partial +passionate +past +pastel +pastoral +pathetic +peaceful +penitent +peppery +perfect +perfumed +periodic +perky +permissible +perpetual +perplexed +personal +pertinent +pesky +pessimistic +petite +petty +petty +phobic +phony +physical +picayune +piercing +pink +piquant +pitiful +placid +plain +plaintive +plant +plastic +plausible +playful +pleasant +pleased +pleasing +plucky +plump +plush +pointed +pointless +poised +polished +polite +political +pompous +poor +popular +portly +posh +positive +possessive +possible +potable +powerful +powerless +practical +precious +premium +present +present +prestigious +pretty +previous +pricey +prickly +primary +prime +pristine +private +prize +probable +productive +profitable +profuse +proper +protective +proud +prudent +psychedelic +psychotic +public +puffy +pumped +punctual +pungent +puny +pure +purple +purring +pushy +pushy +putrid +puzzled +puzzling +quack +quaint +quaint +qualified +quarrelsome +quarterly +queasy +querulous +questionable +quick +quickest +quick-witted +quiet +quintessential +quirky +quixotic +quixotic +quizzical +rabid +racial +radiant +ragged +rainy +rambunctious +rampant +rapid +rare +rash +raspy +ratty +raw +ready +real +realistic +reasonable +rebel +recent +receptive +reckless +recondite +rectangular +red +redundant +reflecting +reflective +regal +regular +reliable +relieved +remarkable +reminiscent +remorseful +remote +repentant +repulsive +required +resolute +resonant +respectful +responsible +responsive +revolving +rewarding +rhetorical +rich +right +righteous +rightful +rigid +ringed +ripe +ritzy +roasted +robust +romantic +roomy +rosy +rotating +rotten +rotund +rough +round +rowdy +royal +rubbery +ruddy +rude +rundown +runny +rural +rustic rusty +ruthless +sable +sad +safe +salty +same +sandy +sane +sarcastic +sardonic +sassy +satisfied +satisfying +savory +scaly +scandalous +scant +scarce +scared +scary +scattered +scented +scholarly +scientific +scintillating +scornful +scratchy +scrawny +screeching +second +secondary +second-hand +secret +secretive +sedate +seemly +selective +self-assured +selfish +self-reliant +sentimental +separate +serene +serious +serpentine +several +severe +shabby +shadowy +shady +shaggy +shaky +shallow +shameful +shameless +sharp +shimmering +shiny +shivering +shocked +shocking +shoddy +short +short-term +showy +shrill +shut +shy +sick +silent +silky +silly +silver +similar +simple +simplistic +sincere +sinful +single +six +sizzling +skeletal +skillful +skinny +sleepy +slight +slim +slimy +slippery +sloppy +slow +slushy +small +smarmy +smart +smelly +smiling +smoggy +smooth +smug +snappy +snarling +sneaky +sniveling +snobbish +snoopy +snotty +sociable +soft +soggy +solid +somber +some +sophisticated +sordid +sore +sorrowful +soulful +soupy +sour +sour +Spanish +sparkling +sparse +special +specific +spectacular +speedy +spherical +spicy +spiffy +spiky +spirited +spiritual +spiteful +splendid +spooky +spotless +spotted +spotty +spry +spurious +squalid +square +squeaky +squealing +squeamish +squiggly +stable +staid +stained +staking +stale +standard +standing +starchy +stark +starry +statuesque +steadfast +steady +steel +steep +stereotyped +sticky +stiff +stimulating +stingy +stormy +stout +straight +strange +strict +strident +striking +striped +strong +studious +stunning +stunning +stupendous +stupid +sturdy +stylish +subdued +submissive +subsequent +substantial +subtle +suburban +successful +succinct +succulent +sudden +sugary +sulky +sunny +super +superb +superficial +superior +supportive +supreme +sure-footed +surprised +suspicious +svelte +swanky +sweaty +sweet +sweltering +swift +sympathetic +symptomatic +synonymous +taboo +tacit +tacky +talented +talkative +tall +tame +tan +tangible +tangy +tart +tasteful +tasteless +tasty +tattered +taut +tawdry +tearful +tedious +teeming +teeny +teeny-tiny +telling +temporary +tempting +ten +tender +tense +tenuous +tepid +terrible +terrific +tested +testy +thankful +that +therapeutic +these +thick +thin +thinkable +third +thirsty +this +thorny +thorough +those +thoughtful +thoughtless +threadbare +threatening +three +thrifty +thundering +thunderous +tidy +tight +tightfisted +timely +tinted +tiny +tired +tiresome +toothsome +torn +torpid +total +tough +towering +tragic +trained +tranquil +trashy +traumatic +treasured +tremendous +triangular +tricky +trifling +trim +trite +trivial +troubled +truculent +true +trusting +trustworthy +trusty +truthful +tubby +turbulent +twin +two +typical +ubiquitous +ugliest +ugly +ultimate +ultra +unable +unaccountable +unarmed +unaware +unbecoming +unbiased +uncomfortable +uncommon +unconscious +uncovered +understated +understood +undesirable +unequal +unequaled +uneven +unfinished +unfit +unfolded +unfortunate +unhappy +unhealthy +uniform +unimportant +uninterested +unique +united +unkempt +unknown +unlawful +unlined +unlucky +unnatural +unpleasant +unrealistic +unripe +unruly +unselfish +unsightly +unsteady +unsuitable +unsung +untidy +untimely +untried +untrue +unused +unusual +unwelcome +unwieldy +unwitting +unwritten +upbeat +uppity +upright +upset +uptight +urban +usable +used +used +useful +useless +utilized +utopian +utter +uttermost +vacant +vacuous +vagabond +vague +vain +valid +valuable +vapid +variable +various +vast +velvety +venerated +vengeful +venomous +verdant +verifiable +versed +vexed +vibrant +vicious +victorious +vigilant +vigorous +villainous +violent +violet +virtual +virtuous +visible +vital +vivacious +vivid +voiceless +volatile +voluminous +voracious +vulgar +wacky +waggish +waiting +wakeful +wan +wandering +wanting +warlike +warm +warmhearted +warped +wary +wasteful +watchful +waterlogged +watery +wavy +weak +wealthy +weary +webbed +wee +weekly +weepy +weighty +weird +welcome +well-documented +well-groomed +well-informed +well-lit +well-made +well-off +well-to-do +well-worn +wet +which +whimsical +whirlwind +whispered +whispering +white +whole +wholesale +whopping +wicked +wide +wide-eyed +wiggly +wild +willing +wilted +winding +windy +winged +wiry +wise +wistful +witty +wobbly +woebegone +woeful +womanly +wonderful +wooden +woozy +wordy +workable +worldly +worn +worried +worrisome +worse +worst +worthless +worthwhile +worthy +wrathful +wretched +writhing +wrong +wry +xenophobic +yawning +yearly +yellow +yellowish +yielding +young +youthful +yummy +zany +zealous +zesty +zigzag +zippy +zonked diff --git a/assets/login_generator.py b/assets/login_generator.py new file mode 100644 index 0000000..29b7974 --- /dev/null +++ b/assets/login_generator.py @@ -0,0 +1,56 @@ +import random +import string + + +def load_file(filename): + """ + We load a file and make a list out of it. Note that the same function is + used for both files (both adjectives and subjects). Functions should be + made as generic as possible. + + There IS a problem you can fix, some logins will have spaces in them. Try + to remove them in this function! + """ + words = [] + with open(filename, "r") as fp: + lines = fp.readlines() + for line in lines: + words.append(line.strip()) # what does strip() do, what does append() do? remember CTRL+Q! + return words + + +def generate_username(): + """ + We'll generate a random pair of adjectives and subjects from two wordlists. + You NEED to have both files in you python project for this to work! Note + the capitalize method call to make it all prettier... + """ + adjectives = load_file("./adjectives.txt") + subjects = load_file("./subjects.txt") + adjective = random.choice(adjectives) + subject = random.choice(subjects) + username = adjective.capitalize() + subject.capitalize() + return username + + +def generate_password(length=10, complictated=True): + """ + We generate a password with default settings. You can overide these by + changing the arguments in the function call. + """ + password = "" + if complictated: + chars = string.ascii_letters + string.digits + string.punctuation + else: + chars = string.ascii_letters + for i in range(0, length): + password += random.choice(chars) + return password + + +if __name__ == "__main__": + # let's do some testing! + username_test = generate_username() + print(username_test) + password_test = generate_password() + print(password_test) diff --git a/assets/pwd_cli.py b/assets/pwd_cli.py new file mode 100644 index 0000000..c5f3830 --- /dev/null +++ b/assets/pwd_cli.py @@ -0,0 +1,61 @@ +import login_generator + + +def prompt(): + """ + We prompt but you KNOW how this works! + """ + response = "" + while not response.isdigit(): + response = input("how many login pairs would you like to create?") + return int(response) + + +def how_long(): + """ + And again... (we could combine both prompts, but how?) + """ + response = "" + while not response.isdigit(): + response = input("how long should the password be?") + return int(response) + + +def complex_or_not(): + response = "" + while response.lower() not in ["y", "n"]: + response = input("you want complex passwords? (y/n)") + if response.lower() == "y": + return True + else: + return False + + +def create_login(length, complicated): + """ + We use our library to generate the username and password. The double return + might look confusing but just look at the for loop in the generate_logins + functions and you'll see how it unpacks... + """ + username = login_generator.generate_username() + password = login_generator.generate_password(length, complicated) + return username, password + + +def generate_logins(number, length, complicated): + """ + Easy no? But what does the i do? Do we really need it's value? + """ + for i in range(0, number): + username, password = create_login(length, complicated) + print("username {}: {}".format(i, username)) + print("password {}: {}".format(i, password)) + + +if __name__ == "__main__": + # Here we go! + number_of_logins = prompt() + complicted = complex_or_not() + length = how_long() + generate_logins(number_of_logins, length, complicted) + diff --git a/assets/subjects.txt b/assets/subjects.txt new file mode 100644 index 0000000..52736ce --- /dev/null +++ b/assets/subjects.txt @@ -0,0 +1,239 @@ +Aardvark +African elephant +Albatross +Alley cat +Alligator +Amphibian +Ant +Anteater +Antelope +Ape +Armadillo +Asian elephant +Baboon +Badger +Bat +Bear +Beaver +Beetle +Billy goat +Bison +Boar +Bobcat +Bovine +Bronco +Buck +Buffalo +Bug +Bull +Bunny +BunnyCalf +Camel +Canary +Canine +Caribou +Cat +Caterpillar +Centipede +Chanticleer +Cheetah +Chick +Chimpanzee +Chinchilla +Chipmunk +Clam +Cockatiel +Colt +Condor +Cougar +Cow +Coyote +Crab +Crane +Creature +Crocodile +Crow +Cub +Cur +Cygnet +Deer +Dingo +Dodo +Doe +Dog +Dolphin +Donkey +Dove +Drake +Duck +Eagle +Egret +Elephant +Elk +Emu +Ewe +Falcon +Fawn +Feline +Ferret +Flamingo +Flee +Flies +Foal +Fowl +Fox +Frog +Gander +Gazelle +Gelding +Gerbil +Gibbon +Giraffe +Goat +Goose +Gopher +Gorilla +Grizzly bear +Guinea pig +Hamster +Hare +Hawk +Hedgehog +Heifer +Hippopotamus +Horse +Hound +Hummingbird +Hyena +Ibis +Iguana +Jackal +Jackrabbit +Jaguar +Javalina +Jellyfish +Jenny +Joey +Kangaroo +Kid +Kitten +Kiwi +Koala +Komodo dragon +Krill +Lamb +Lemming +Lemur +Leopard +Lion +Lioness +Llama +Lobster +Lynx +Macaw +Manatee +Marmoset +Marmot +Mink +Minnow +Mite +Mockingbird +Mole +Mongoose +Mongrel +Monkey +Moose +Mouse +Mule +Mustang +Mutt +Nag +Narwhale +Newt +Ocelot +Octopus +Opossum +Orangutan +Orca +Osprey +Ostrich +Otter +Owl +Ox +Pachyderm +Panda +Panther +Parakeet +Parrot +Peacock +Pelican +Penguin +Pheasant +Pig +Pigeon +Piglet +Platypus +Pony +Pooch +Porcupine +Porpoise +Primate +Puppy +Pussycat +Rabbit +Raccoon +Ram +Rat +Reptiles +Rhinoceros +Robin +Rooster +Salamander +Sea lion +Seagull +Seal +Sheep +Sidewinder +Skunk +Sloth +Snail +Snake +Songbird +Sow +Spider +Squid +Squirrel +Stallion +Steer +Stork +Stork +Swan +Tadpole +Tapir +Terrapin +Thoroughbred +Tiger +Toad +Tortoise +Toucan +Turkey +Uakari +Unicorn +Vixen +Vole +Vulture +Wallaby +Walrus +Warthog +Wasp +Weasel +Whale +Wildebeast +Wolf +Wombat +Woodpecker +Worm +X-ray fish +Yak +Zebra + diff --git a/learning_python3.md b/learning_python3.md index e14a8da..7109132 100644 --- a/learning_python3.md +++ b/learning_python3.md @@ -1072,67 +1072,815 @@ There are a couple of things you should definitely read up on. # While loop -TODO guess the number exercise +We started our python journey with fully linear code. +Next we saw functions which are first **defined** and called afterwards. +Now we'll have a look at **loops**. +In python there are **two** types of loops, a **while** and a **for** loop. +We'll start with the while loop which I see as a loop in *time*. +The for loop is a loop in *space* but we'll get to that one later. + +The concept of a while loop is pretty simple. +Code **within** the loop will be executed as long as a **condition** is met. +Consider the code below. + +```python3 +import time + +counter = 0 +print("before the loop, counter: {}".format(counter)) + +while counter <= 10: + print("inside the loop, counter: {}".format(counter)) + counter += 1 + time.sleep(1) + +print("after the loop, counter: {}".format(counter)) +``` + +Two *extra* things might look new to you here. +First the `import time` and `time.sleep(1)`, can you tell me what it does? +Next the `counter += 1` which is called [incrementing](https://stackoverflow.com/questions/1485841/behaviour-of-increment-and-decrement-operators-in-python). +You'll find this feature in most languages. +You can think of it's syntax as *counter equals itself plus 1*. +The *1* can be any number you want though! + +When learning the `while` [keyword](https://docs.python.org/3/reference/compound_stmts.html#the-while-statement) there is a *second* keyword you should learn. +It comes in very handy when constructing [infinite loops](https://en.wikipedia.org/wiki/Infinite_loop). +Consider the following code. + +```python3 +import time + +counter = 0 +print("before the loop, counter: {}".format(counter)) + +while True: + print("inside the loop, counter: {}".format(counter)) + counter += 1 + time.sleep(1) + +print("after the loop, counter: {}".format(counter)) +``` + +The `while True` condition is *always* `True` so the loop will **never** exit! +This is what we call an infinite loop. +The `break` keyword was added to the language so we can *break out* of a loop. +The logic is as follows. + +```python3 +import time + +counter = 0 +print("before the loop, counter: {}".format(counter)) + +while True: + print("inside the loop, counter: {}".format(counter)) + counter += 1 + if counter >= 10: + print("I'll break now!") + break + time.sleep(1) + +print("after the loop, counter: {}".format(counter)) +``` + +Infinite loops are a cornerstone of modern programming. +While they might look scary, don't overthink it, you'll get used to them very quickly. + +⛑ **When testing out an infinite loop it's sometimes handy to insert a `time.sleep` in it to slow down the execution a bit so you can wrap your head around what's happening.** + +🏃 Try it +--- + +Go back to the Celsius to Farenheit converter and add a while loop to ensure the user put's in only numbers. + + +# Coding challenge - Guess the number + +Now that you know how to repeat code execution we can create our first game! +Everybody knows the *guess the number* game. +The computer chooses a *random* number and the user has to *guess* which number it is. +At each try the computer will till you if the user's number is bigger or smaller *than* the one the computer has in mind. +The flow of the game could be as follows. + +``` +I have a number in mind... +What's your guess? 50 +my number is bigger +What's your guess? 80 +my number is smaller +What's your guess? blabla +that's not a number! try again... +What's your guess? 76 +yes, that's right! you win! +bye bye... +``` + +
+ Spoiler warning + +```python3 +import random + + +def ask_for_number(): + result = input("What's your guess? ") + if result.isdigit(): + number = int(result) + return number + else: + return None + + +if __name__ == "__main__": + number_to_guess = random.randint(0, 100) + print("I have a number in mind...") + while True: + user_number = ask_for_number() + if user_number is None: + print("that's not a number! try again...") + continue + elif number_to_guess == user_number: + print("yes, that's right! you win!") + break + elif number_to_guess > user_number: + print("my number is bigger") + elif number_to_guess < user_number: + print("my number is smaller") + print("bye bye...") +``` + +
+ +🏃 Try it +--- + +My *solution* is very basic. +Think of some ways to improve on it. +Can you limit the number of tries? +Can you add a feature to let the user play a *second* game after he/she wins or loses? +Coming up with challenges is on of the most *challenging* aspect op learning how to program. +Your thought process will send you of into unknown territory and will force you to expand you knowledge. +We'll get back to this thought process later, but if you feel like an extra challenge go for it! # Lists +The different built-in objects we've seen until now, such as `str` and `int` are simple [text](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str) and [numeric](https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex) types. +There are other classes of objects that server different purposes. +One of these *groups* is called [sequence types](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range). + +A list in python is pretty much exactly what you think it is. +It is an *object* that groups together *other* objects. +Sounds complicated? +Have a look at the following. + +```python3 +my_numbers = [1, 2, 44, 60, 70] +print(my_numbers) +``` + +Easy right? +Compared to [other languages](https://www.cplusplus.com/reference/list/list/) lists in python are *very* flexible. +They can contain objects of different types, and their length can be changed at any time. +Programmers coming from other languages often find this flexibility of python a bug but you should see it as a feature. + +```python3 +favorite_number = 7 +name = "wouter" +date = [1986, 10, 7] +values = [1, date, favorite_number, "hello world", name] + +print(values) +``` + +The code above is just an illustration of the flexibility of lists. + ## Creating lists -## Picking elements +Creating lists can be done in two ways, either by using the **square brackets** `[]` or by calling `list`. +When calling `list` it takes **one argument**, which python will iterate over. +For example: -## Slicing lists +```python3 +>>> first_list = ["hello", "world", "!"] +>>> first_list +['hello', 'world', '!'] +>>> second_list = list("hello world !") +>>> second_list +['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', ' ', '!'] +>>> +``` + +## List methods + +As a `list` is a different type of object, it has different methods you can invoke on it. +When using tab complete in the python shell we get the following. + +```python3 +>>> second_list. +second_list.append( second_list.count( second_list.insert( second_list.reverse( +second_list.clear( second_list.extend( second_list.pop( second_list.sort( +second_list.copy( second_list.index( second_list.remove( +>>> second_list. +``` + +One of the most used methods is `append`. +It is used to add an element to the end of the list. +The second most used method is the `pop` one. +Read the shell code below and you'll understand immediately what they do. + +```python3 +>>> first_list +['hello', 'world', '!'] +>>> first_list.append("coucou") +>>> first_list +['hello', 'world', '!', 'coucou'] +>>> first_list.pop() +'coucou' +>>> first_list +['hello', 'world', '!'] +>>> +``` + +🏃 Try it +--- + +Look at all the methods you can invoke on a list and try them out. +Remember to read the documentation! + +## Picking elements and slicing lists + +We can pick elements from the list of slice the list as we please. +A code block speaks more than words. + +```python3 +>>> long_list +['I', 'am', 'a', 'very', 'long', 'list', 'of', 'words', 'that', 'make', 'little', 'actual', 'sense'] +>>> long_list[7] +'words' +>>> long_list[7:9] +['words', 'that'] +>>> long_list[7:] +['words', 'that', 'make', 'little', 'actual', 'sense'] +>>> long_list[:7] +['I', 'am', 'a', 'very', 'long', 'list', 'of'] +>>> long_list[-1] +'sense' +>>> long_list[0] +'I' +>>> +``` + +⛑ **In programming we start counting at 0 because 0 and nothing are not the same thing.** + +🏃 Try it +--- + +Slice and dice away! +A handy method of the `str` class is `split` which will cut up a string into separate elements. +The result will be a `list` on which you can use `list` methods. # For loop -TODO say hello to my friends exercise -TODO simple ROT13 cryptography with multiple libs +I mentioned the for loop, which is a loop in space, when we saw the `while` loop. +The [keyword](https://docs.python.org/3/reference/compound_stmts.html#the-for-statement) in question is, surprise surprise, `for`! +I see it as a loop in space because it will run *for each element in a sequence* which in my mind is something of substance. +Your logical mileage may vary but as long as you understand the following code block we're good. + +```python3 +import time + +friends = ["max", "mike", "alice", "steve", "rosa", "hans"] + +print("The door opens and in walk my {} friends!".format(len(friends))) + +for friend in friends: + print("Hello {}!".format(friend.capitalize())) + time.sleep(1) + +print("{} closes the door behind him...".format(friend.capitalize())) +``` # Coding challenge - Cheerleader chant -TODO nested for loop exercise +Can you make me a program that outputs this type of cheerleader chant? +You can make it *prettier* by importing your `pretty_print` function, plus you can add some `time.sleep` in it to make it more *musical*. + +``` +Give me an m +M +Give me an a +A +Give me an x +X +Gooooooooo, MAX! +Give me an m +M +Give me an i +I +Give me an k +K +Give me an e +E +Gooooooooo, MIKE! +Give me an c +C +Give me an a +A +Give me an m +M +Give me an i +I +Give me an l +L +Give me an l +L +Give me an e +E +Gooooooooo, CAMILLE! +``` + +
+ Spoiler warning + +```python3 +friends = ["max", "mike", "camille"] + + +for friend in friends: + for letter in friend: + print("Give me an {}".format(letter)) + print("{}".format(letter.upper())) + print("Gooooooooo, {}!".format(friend.upper())) +``` + +
+ +# Coding challenge - ROT13 + +ROT13 is one of the oldest cryptographic cyphers know to mankind. +It dates back to the Roman empire and is also known as a [Caesar cypher](https://en.wikipedia.org/wiki/Caesar_cipher). +The algorithm is pretty simple, you just shift a letter 13 places in the alphabet so `a` becomes `n` or `x` becomes `k`. +Have a look at [this](https://rot13.com/) website to see the cypher in action. +Now, can you make a program that encrypts a phrase with ROT13? +Something along these lines: + +```python3 +What's your secret? hello world! +encoded secret: uryyb jbeyq! +``` + +
+ Spoiler warning + +```python3 +import string + + +def encode_rot(msg, rot=13): + msg = msg.lower() + letters = list(string.ascii_lowercase) + coded_msg = [] + for letter in msg: + if letter not in letters: + coded_msg.append(letter) + else: + idx = letters.index(letter) + rot + coded_letter = letters[idx % len(letters)] + coded_msg.append(coded_letter) + coded_msg = "".join(coded_msg) + return coded_msg + + +def decode_rot(msg, rot=13): + pass + + +if __name__ == "__main__": + clear_message = input("What's your secret? ") + encoded_message = encode_rot(clear_message) + print("encoded secret: {}".format(encoded_message)) +``` + +
+ +🏃 Try it +--- + +To make things more interesting you can add a decode function. +Plus you could add a prompt that asks how big the shift should be (ROT13, ROT16, ...). + +# List comprehension + +This is a bit of an advanced topic but I'm putting it here to show you a very unique and powerful feature of python. +It's an *in-line* combination of `list`, `for` and conditional logic which allows us to make lists of lists which obey certain conditions. +You can [learn](https://12ft.io/proxy?q=https%3A%2F%2Frealpython.com%2Flist-comprehension-python%2F) about it online. + +```python3 +mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"] + +digits = [d for d in mixed_list if d.isdigit()] + +print(digits) +``` + +The code above can be recreated **without** list comprehension as well, it will just be *a lot* longer. + +```python3 +mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"] + +digits = [] +for d in mixed_list: + if d.isdigit(): + digits.append(d) + +print(digits) +``` + +As the `d` in the list comprehension is **always** a digit, we can convert it to an integer on the spot! + +```python3 +mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"] + +digits = [int(d) for d in mixed_list if d.isdigit()] + +print(digits) +``` # Handling files +When we `import` a library python will read and execute the file in question. +We can also just *read* a simple text file and *use* the data that's in the file. +There are two ways of reading a file, one more *pythonic* and one more linear. +I'll outline both and you can use whichever seems more logical to you. + ## Reading from a file +### In-line way + +The builtin function `open` is what's new here. +It takes two arguments, one is the [path](https://en.wikipedia.org/wiki/Path_(computing)) and the other is a *mode*. +The most used modes are **read** or **write**, and this as either **text** or **binary**. +Have a look at the documentation to discover more modes. + +```python3 +fp = open("./examples/data.txt", "r") +data = fp.readlines() +print("file contains: {}".format(data)) +fp.close() +``` + +### Pythonic way + +The *exact* same thing can be done in a more pythonic way as follows. +The beauty of the `with` syntax is that the `close` function call is implied by the indentation. +I personally prefer this way of reading and writing files but you do you! + +```python3 +file_to_open = "./examples/data.txt" + +with open(file_to_open, "r") as fp: + data = fp.readlines() + print("file contains: {}".format(data)) + +print("{} has {} lines".format(file_to_open, len(data))) +``` + ## Writing to a file -## csv, JSON and yaml +Writing to a file can also be done in two ways, a pythonic and *less* pythonic way. +As I prefer the pythonic way I'll only showcase that one but you'll be able to easily adapt the code yourself. +The only difference is the **mode** we use to `open` the file. -## pickle +```python3 +first_name = input("what's your first name? ") +last_name = input("what's your last name? ") +birthday = input("what's your date of birth? ") + +data = [first_name, last_name, birthday] + +file_to_open = "./examples/test.tmp" + +with open(file_to_open, "w") as fp: + for element in data: + fp.write("{}\n".format(element)) +print("done!") +``` + +There is also a way to write a batch of lines to a file in one go. +This is done as follows. +But, you'll notice there is no **newline** added after each element. + +```python3 +data = ["wouter", "gordts", "1986"] + +file_to_open = "./examples/test.tmp" + +with open(file_to_open, "w") as fp: + fp.writelines(data) +``` # Coding challenge - Login generator -TODO write a login generator as a library with a cli as program -BONUS argparse, save to file, read from file +Can you write me a program that creates random, but easy to remember, usernames? +Plus, for each username also a *not-so-easy-to-remember* password? +Maybe with a bit of flexibility? +For example variable password length? + +This is an exercise you can take pretty far if you plan it out properly. +I would advise you to write the **generator** functions as a library. +Then import those functions into the program where you implement the user facing logic. +By doing so you can reuse your code for multiple interfaces (CLI, TUI, [argparse](https://docs.python.org/3/howto/argparse.html)). +If you want to you can also **save** your logins to a file! + +An example of the output I expect: + +``` +how many login pairs would you like to create?3 +you want complex passwords? (y/n)y +how long should the password be?32 +username 0: EarnestCrocodile +password 0: :sdGV&[FDYZZ|RXUpZeo`J&t@*Z>^fEW +username 1: AbstractedDragon +password 1: 32hz5&C@ + Spoiler warning + +This spoiler warning is in multiple steps. +If you're unsure how to generate the *random-yet-easy-to-remember* have a look at [this file](./assets/subjects.txt) and [this file](./assets/adjectives.txt). + +**Stop here and try it out!** + +If you're unsure how to tackle the *library part* of this exercise, have a look at [this file](./assets/login_generator.py). +Don't just copy this code, read it and recreate it yourself! + +**Stop here and try it out!** + +Once the library is done you can code the *interface*. +For some inspiration for a simple question/response system you can have a look [here](./assets/pwd_cli.py). + + # Dictionaries as data containers -TODO adapt the login generator to output a dict +Of the *built-in* types we first say `str`, `int` and `float`. +Next we saw *sequence* types such as `list` and `tupple`. +Now we'll dive into a **mapping type** called `dict`. +I advise you to have a look at the [reference pages](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) when in doubt. -# Creating our own classes +A dictionary is *kind* of like a list but it has **two** objects per **element**. +We call them **key** and **value**. +There are a couple of rules you need to be aware of though. -## Class examples +1. In a `dict` the keys have to be **unique**. +2. A dictionary is **unordered** meaning the *first* element is not garanteed to remain the first over the lifespan of the dictionary. +3. The keys used must be **hashable**. + +Let's visualize a legal dictionary! +It's declared with **curly brackets** as follows `{}`. + +```python3 +my_data = {"key": "value", "name": "wouter", "age": 35} + +same_data_different_layout = { + "key": "value", + "name": "wouter", + "age": 35, + } +``` + +Let's have a look at the **methods** we can invoke on a `dict`. + +```python3 +>>> my_data = {"key": "value", "name": "wouter", "age": 35,} +>>> my_data. +my_data.clear( my_data.get( my_data.pop( my_data.update( +my_data.copy( my_data.items( my_data.popitem( my_data.values( +my_data.fromkeys( my_data.keys( my_data.setdefault( +>>> my_data.keys() +dict_keys(['key', 'name', 'age']) +>>> my_data.values() +dict_values(['value', 'wouter', 35]) +>>> my_data.items() +dict_items([('key', 'value'), ('name', 'wouter'), ('age', 35)]) +>>> for key, value in my_data.items(): +... print("key is {}".format(key)) +... print("value is {}".format(value)) +... +key is key +value is value +key is name +value is wouter +key is age +value is 35 +>>> +``` + +We can reference specific **values** corresponding to specific **keys** as follows. + +```pythons +>>> my_data["name"] +'wouter' +>>> my_data["age"] +35 +>>> +``` + +We can use dictionaries as data containers and put them in a list to group together similar data elements. +The code below should explain it quite nicely. + +```python3 +login_ovh = {"username": "EarnestCrocodile", "password": ":sdGV&[FDYZZ|RXUpZeo`J&t@*Z>^fEW"} +login_mailbox = {"username": "AbstractedDragon", "password": "32hz5&C@ + Spoiler warning + +```python3 +import argparse +import pathlib + + +def read_taskfile(taskfile_path): + tasks = [] + if not pathlib.Path(taskfile_path).exists(): + return tasks + with open(taskfile_path, "r") as fp: + lines = fp.readlines() + for line in lines: + task = line.strip() + tasks.append(task) + return tasks + + +def write_taskfile(taskfile_path, tasks): + with open(taskfile_path, "w") as fp: + for task in tasks: + fp.write("{}\n".format(task)) + + +def show_tasks(tasks): + counter = 0 + for task in tasks: + print("ID: {} --- {}".format(counter, task)) + counter += 1 + + +def add_task(tasks, task): + tasks.append(task) + return tasks + + +def delete_task(tasks, task_id): + tasks.pop(task_id) + return tasks + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--file", "-f", default="./todo.tasks", help="path to your todo file") + subparser = parser.add_subparsers() + add = subparser.add_parser("add", help="adds a todo item to you todo list") + add.add_argument("task", nargs="*") + delete = subparser.add_parser("delete", help="deletes an item from your todo list") + delete.add_argument("idx", type=int, nargs="*") + show = subparser.add_parser("show", help="show all your tasks") + show.add_argument("show", action="store_true") + args = parser.parse_args() + + taskfile = args.file + tasks = read_taskfile(taskfile) + + if "task" in args: + tasks = add_task(tasks, " ".join(args.task)) + write_taskfile(taskfile, tasks) + elif "idx" in args: + for idx in args.idx: + tasks = delete_task(tasks, idx) + write_taskfile(taskfile, tasks) + elif args.show: + show_tasks(tasks) +``` + + +# Text based databases + +The todo list example from before is handy but quite *limited* as a database. +As is it only holds one form or information and that is the *actual task*. +What if we want to add urgency or mark tasks complete (instead of deleting)? +This can be done by grouping data together. +We already saw a dictionaries which are good mapping structures but how can we save them to disk? +A hacky way would be to write a python file containing the `dict` and `import` it when we need it. +But there are better ways. + + +# Now for some useful scripting + +With everything we have learned up until now you can start doing some interesting and useful things. +Have a look at [these exercises](https://gitea.86thumbs.net/waldek/linux_course_doc/src/branch/master/modules/qualifying/exercise_python.md). +You can try them out at your own pace. +I can give some hints or pointers if needed, either in class or individually. +Don't hesitate to ask for help! + +# Creating our own objects + +## First some *abstract* examples TODO simple animal or vehicle exercise -TODO task manager ## Class inheritance TODO shapes and surfaces -TODO superhero game -## Improve the login generator +## Now some *practical* improvements + +### Improve the login generator TODO convert the login generator to a class +### Improve the task manager + +TODO convert the task manager to a class + # Infinite programs * insist on the nature of scripts we did up until now ## Logic breakdown of a simple game -TODO hangman exercise +``` +*********************** +* welcome to hangman! * +*********************** + +guess the hidden word below +--------------------------- +word: ***** +guess a letter: a +word: a**** +guess a letter: l +word: a**l* +guess a letter: p +word: appl* +guess a letter: e +word: apple +***************** +* you found it! * +***************** +do you want to play a new game? (Y/N) +``` ## Trivial pursuit multiple choice game